This commit was generated by cvs2svn to compensate for changes in r548,
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 10 Nov 2003 15:13:57 +0000 (15:13 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 10 Nov 2003 15:13:57 +0000 (15:13 +0000)
which included commits to RCS files with non-trunk default branches.

st2gpx/istorage/istorage.cpp [new file with mode: 0644]
st2gpx/src/COPYING [new file with mode: 0644]
st2gpx/src/getopt.c [new file with mode: 0644]
st2gpx/src/getopt.h [new file with mode: 0644]
st2gpx/src/pushpins.cpp [new file with mode: 0644]
st2gpx/src/pushpins.h [new file with mode: 0644]
st2gpx/src/st2gpx.c [new file with mode: 0644]
st2gpx/src/st2gpx.dsp [new file with mode: 0644]
st2gpx/src/st2gpx.dsw [new file with mode: 0644]

diff --git a/st2gpx/istorage/istorage.cpp b/st2gpx/istorage/istorage.cpp
new file mode 100644 (file)
index 0000000..995b856
--- /dev/null
@@ -0,0 +1,261 @@
+/*by Pabs (pabs3@zip.to, http://zip.to/pabs3) Nov 2001, April 2002*/\r
+\r
+/*Licenced under the BSD sloppyright - nasty little daemons better not use this source & not attribute me*/\r
+/*Why BSD licence? HTFSIK but seriously I wanted to get to know more open/free licences*/\r
+\r
+/*Compile notes:\r
+       M$VC: just open this file & press the build button or select build from the\r
+             build menu since this will create a default project that does nicely\r
+       GCC/Cygwin: gcc -mno-cygwin -fvtable-thunks -lole32 -o istorage.exe istorage.cpp should do the trick\r
+                   if w32api & mingw are set up correctly & the headers are correct\r
+       GCC/Wine: You'll have to figure it out for yourself since I don't yet have\r
+                 access to Linux (Debian) cause I need a new HD + a DVD drive ;-)\r
+*/\r
+\r
+/*Usage:\r
+       istorage some.doc some.xls some.pub some.fla some.chm\r
+               will extract each of these files to some.???.Contents directories\r
+               these are M$ Word, Excel and Publisher and Macromedia Flash source files (ooh and a compiled HTML Help file)\r
+*/\r
+\r
+/*TODO:\r
+       think up a proper name - unist??? or what??\r
+       Add popt/getopt processing\r
+       reverse engineer the compound file format (& chm format - Matthew T. Russotto has already done some)\r
+       or just use libOLE - http://chicago.sf.net\r
+       so we don't depend on M$ for the implementation\r
+       Implement options for the following\r
+               -i string  invalid chars\r
+               -f char    replace invalid chars with\r
+               -n char    indent with this char\r
+               -a string  append this to each file opened\r
+               various tar/unzip options\r
+               --help --version\r
+*/\r
+\r
+\r
+#include <windows.h>\r
+#include <ole2.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+\r
+struct OPTIONS{\r
+       char fixchar;\r
+       char* invalidchars;\r
+       char indentchar;\r
+       char* appendstring;\r
+} options = {'.',"<>|/\\\"",'\t',".Contents"};\r
+\r
+HRESULT r;\r
+\r
+DWORD level = 0;\r
+\r
+//These next few bits are from a sample available from http://www.keyworks.net/code.htm (see http://helpware.net/delphi/index.html for a Delphi sample - need to join a yahoo group first - example 10 is the one to look at)\r
+//This stuff is supposed to be documented in the MSDN, but I only found 1 page that references ITStorage & that is an error codes list\r
+DEFINE_GUID(CLSID_ITStorage, 0x5d02926a, 0x212e, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);\r
+DEFINE_GUID(IID_ITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);\r
+\r
+const GUID CLSID_ITStorage = { 0x5d02926a, 0x212e, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec } };\r
+const GUID IID_ITStorage = { 0x88cc31de, 0x27ab, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec} };\r
+\r
+typedef struct _ITS_Control_Data\r
+{\r
+       UINT cdwControlData; // Number of DWords to follow.\r
+       UINT adwControlData[1]; // Actually this will be adwControlData[cdwControlData]\r
+} ITS_Control_Data, *PITS_Control_Data;\r
+\r
+typedef enum ECompactionLev {\r
+       COMPACT_DATA = 0,\r
+       COMPACT_DATA_AND_PATH\r
+};\r
+\r
+DECLARE_INTERFACE_(IITStorage, IUnknown)\r
+{\r
+       STDMETHOD(StgCreateDocfile) (const WCHAR* pwcsName, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE;\r
+       STDMETHOD(StgCreateDocfileOnILockBytes) (ILockBytes * plkbyt, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE;\r
+       STDMETHOD(StgIsStorageFile) (const WCHAR * pwcsName) PURE;\r
+       STDMETHOD(StgIsStorageILockBytes) (ILockBytes * plkbyt) PURE;\r
+       STDMETHOD(StgOpenStorage)(const WCHAR * pwcsName, IStorage * pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE;\r
+       STDMETHOD(StgOpenStorageOnILockBytes)(ILockBytes * plkbyt, IStorage * pStgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE;\r
+       STDMETHOD(StgSetTimes)(WCHAR const* lpszName, FILETIME const* pctime, FILETIME const* patime, FILETIME const* pmtime) PURE;\r
+       STDMETHOD(SetControlData)(PITS_Control_Data pControlData) PURE;\r
+       STDMETHOD(DefaultControlData)(PITS_Control_Data *ppControlData) PURE;\r
+       STDMETHOD(Compact)(const WCHAR* pwcsName, ECompactionLev iLev) PURE;\r
+};\r
+\r
+IITStorage* ITStorage = NULL;\r
+\r
+void EnumStorage(IStorage* is);\r
+void fixpath(char* s);\r
+\r
+int main(int argc, char *argv[]){\r
+       //Get an instance of the thing to call for opening chms\r
+       CoInitialize(NULL);\r
+       CoCreateInstance(CLSID_ITStorage, NULL, CLSCTX_INPROC_SERVER, IID_ITStorage, (void**)&ITStorage);\r
+       for(int i=1;i<argc;i++){\r
+               for(DWORD ii=0;ii<level;ii++)fputc(options.indentchar,stderr);\r
+               fputs(argv[i],stderr);\r
+               fputs(": ",stderr);\r
+               DWORD len = strlen(argv[i]);\r
+               DWORD wlen = MultiByteToWideChar(CP_ACP,0,argv[i],len+1,NULL,0);\r
+               WCHAR* wpath = new WCHAR[len+1];\r
+               if(wpath){\r
+                       if(MultiByteToWideChar(CP_ACP,0,argv[i],len+1,wpath,wlen)){\r
+                               IStorage* is = NULL;\r
+                               r = StgOpenStorage(wpath,NULL,STGM_READ|STGM_SHARE_EXCLUSIVE,NULL,0,&is);\r
+                               if( ITStorage && r != S_OK && is == NULL ){\r
+                                       r = ITStorage->StgOpenStorage(wpath,NULL,STGM_READ|STGM_SHARE_DENY_WRITE,NULL,0,&is);\r
+                                       fputs("StgOpenStorage failed, trying chm version...",stderr);\r
+                               }\r
+                               delete[]wpath; wpath = NULL;\r
+                               if( r == S_OK || is ){\r
+                                       STATSTG ss;\r
+                                       if(S_OK==is->Stat(&ss,STATFLAG_NONAME))fprintf(stderr,"CLSID={%8.8X-%4.4X-%4.4X-%4.4X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X} State=0x%8.8X reserved=0x%8.8X\n", ss.clsid.Data1, ss.clsid.Data2, ss.clsid.Data3, ss.clsid.Data4[0]<<8/*&0xff00*/| ss.clsid.Data4[1], ss.clsid.Data4[2], ss.clsid.Data4[3], ss.clsid.Data4[4], ss.clsid.Data4[5], ss.clsid.Data4[6], ss.clsid.Data4[7], ss.grfStateBits, ss.reserved);\r
+                                       else fputs("Stat failed\n",stderr);\r
+                                       char* path = new char[len+strlen(options.appendstring)+1];\r
+                                       if(path){\r
+                                               strcpy(path,argv[i]);\r
+                                               strcpy(&path[len],options.appendstring);\r
+                                               RemoveDirectory(path);\r
+                                               if(CreateDirectory(path,NULL)||GetLastError()==ERROR_ALREADY_EXISTS){\r
+                                                       if(SetCurrentDirectory(path)){\r
+                                                               delete[]path; path = NULL;\r
+                                                               level++;\r
+                                                               EnumStorage(is);\r
+                                                               level--;\r
+                                                               SetCurrentDirectory("..");\r
+                                                       }\r
+                                                       else fputs("Could not enter - Ignoring & continuing\n",stderr);\r
+                                               }\r
+                                               else fputs("Could not create (directory) - Ignoring & continuing\n",stderr);\r
+                                               delete[]path; path = NULL;\r
+                                       }\r
+                                       else fputs("Could not alloc memory for the ANSI pathname for the wimpy Win9$ - Ignoring & continuing\n",stderr);\r
+                                       is->Release();\r
+                               }\r
+                               else fputs("Could not open the specified file - Ignoring & continuing\n",stderr);\r
+                       }\r
+                       else fputs("Could not convert the path to Unicode for the Unicode only StgOpenStorage - Ignoring & continuing\n",stderr);\r
+                       delete[]wpath; wpath = NULL;\r
+               }\r
+               else fputs("Could not alloc memory for the Unicode filename for the Unicode only StgOpenStorage - Ignoring & continuing",stderr);\r
+       }\r
+       if( ITStorage ) ITStorage->Release();\r
+       CoUninitialize();\r
+       fflush(stderr);//Helps with debugging\r
+       return 0;\r
+}\r
+\r
+void EnumStorage(IStorage* is){\r
+       IEnumSTATSTG* iess;\r
+       r = is->EnumElements(0,NULL,0,&iess);\r
+       if( r!= S_OK ) { fputs("Could not enumerate elements - Ignoring & continuing\n",stderr); return;}\r
+       STATSTG ss;\r
+       iess->Reset();\r
+       for(;;){\r
+               r=iess->Next(1,&ss,NULL);\r
+               if( r!= S_OK ) break;\r
+               for(DWORD i=0;i<level;i++)fputc(options.indentchar,stderr);\r
+               fputws(ss.pwcsName,stderr);\r
+               fputs(": ",stderr);\r
+               fprintf(stderr,"CLSID={%8.8X-%4.4X-%4.4X-%4.4X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X} State=0x%8.8X reserved=0x%8.8X\n", ss.clsid.Data1, ss.clsid.Data2, ss.clsid.Data3, ss.clsid.Data4[0]<<8/*&0xff00*/| ss.clsid.Data4[1], ss.clsid.Data4[2], ss.clsid.Data4[3], ss.clsid.Data4[4], ss.clsid.Data4[5], ss.clsid.Data4[6], ss.clsid.Data4[7], ss.grfStateBits, ss.reserved);\r
+               DWORD len = wcslen(ss.pwcsName);\r
+               char* path = new char[len+1];\r
+               if(path){\r
+                       if(WideCharToMultiByte(CP_ACP,0,ss.pwcsName,len+1,path,len+1,NULL,NULL)){\r
+                               fixpath(path);\r
+                               switch(ss.type){\r
+                                       case STGTY_STORAGE:{\r
+                                               IStorage* is2;\r
+                                               r = is->OpenStorage(ss.pwcsName,NULL,STGM_READ|STGM_SHARE_EXCLUSIVE,NULL,0,&is2);\r
+                                               CoTaskMemFree(ss.pwcsName); ss.pwcsName = NULL;\r
+                                               if( r == S_OK || is2 ){\r
+                                                       if(CreateDirectory(path,NULL)||(r=GetLastError())==ERROR_ALREADY_EXISTS){\r
+                                                               if(r==ERROR_ALREADY_EXISTS)fputs("Already exists (directory) - using anyway\n",stderr);\r
+                                                               else fputs("Created (directory)\n",stderr);\r
+                                                               HANDLE f = CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);\r
+                                                               if(f!=INVALID_HANDLE_VALUE&&f!=0/*Fucking lying MSDN*/){\r
+                                                                       if(!SetFileTime(f,&ss.ctime,&ss.atime,&ss.mtime))fputs("Could not set the creation, last modification or last access time\n",stderr);\r
+                                                                       CloseHandle(f);\r
+                                                               }\r
+                                                               if(SetCurrentDirectory(path)){\r
+                                                                       delete[]path; path = NULL;\r
+                                                                       level++;\r
+                                                                       EnumStorage(is2);\r
+                                                                       level--;\r
+                                                                       SetCurrentDirectory("..");\r
+                                                               }\r
+                                                               else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr);\r
+                                                       }\r
+                                                       else fputs("Could not create (directory) - Ignoring & continuing\n",stderr);\r
+                                                       is2->Release();\r
+                                               }\r
+                                               else fputs("Could not open (directory) - Ignoring & continuing\n",stderr);\r
+                                       }break;\r
+                                       case STGTY_STREAM:{\r
+                                               IStream* is2;\r
+                                               r = is->OpenStream(ss.pwcsName,NULL,STGM_READ|STGM_SHARE_EXCLUSIVE,0,&is2);\r
+                                               CoTaskMemFree(ss.pwcsName); ss.pwcsName = NULL;\r
+                                               if( r == S_OK ){\r
+                                                       HANDLE f = CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);\r
+                                                       delete[]path; path = NULL;\r
+                                                       if(f!=INVALID_HANDLE_VALUE&&f!=0/*Fucking lying MSDN*/){\r
+                                                               if(ERROR_ALREADY_EXISTS==GetLastError())fputs("Already exists (file) - overwriting\n",stderr);\r
+                                                               else fputs("Created (file)\n",stderr);\r
+                                                               //This bit, although a bit more complex than 1 byte at a time, is way faster\r
+                                                               BYTE* p;\r
+                                                               ULARGE_INTEGER i={0};\r
+                                                               DWORD nobm = (DWORD)ss.cbSize.QuadPart, nobr, nobw;\r
+                                                               bool err;\r
+                                                               for(;;){\r
+                                                                       p = (BYTE*)malloc( nobm ); if(p)break;\r
+                                                                       nobm/=2; if(!nobm)break;\r
+                                                               }\r
+                                                               if(p){\r
+                                                                       do{\r
+                                                                               r=is2->Read(p,nobm,&nobr);\r
+                                                                               if(r!=S_OK&&nobm!=nobr){fputs("Read error (file) - terminating this file\n",stderr);err=true;}//read less than asked and there was an error other than EOF - MSDN says that the compound file implementation of Read returns S_OK if the end of the stream was reached during the read\r
+                                                                               nobw=0;\r
+                                                                               r=WriteFile(f,p,nobr,&nobw,NULL);\r
+                                                                               i.QuadPart+=nobw;\r
+                                                                               if(!r||nobr!=nobw){fputs("Write error (file) - terminating this file\n",stderr);err=true;}\r
+                                                                       } while (i.QuadPart<ss.cbSize.QuadPart&&!err);\r
+                                                                       free(p); p = NULL;\r
+                                                               }\r
+                                                               //Note that for(uint i=randint();!i;i/=2); will always go through i=1 to i=0\r
+                                                               else{ fputs("Could not alloc even 1 byte of mem for a buffer for transferring files - please free some memory & try again - Ignoring & continuing\n",stderr); err=true;}\r
+                                                               if(!SetFileTime(f,&ss.ctime,&ss.atime,&ss.mtime))fputs("Could not set the creation, last modification or last access time - Ignoring & continuing\n",stderr);\r
+                                                               CloseHandle(f);\r
+                                                       }\r
+                                                       else fputs("Could not create (file) - Ignoring & continuing\n",stderr);\r
+                                                       is2->Release();\r
+                                               }\r
+                                               else fputs("Could not open (file) - Ignoring & continuing\n",stderr);\r
+                                       }break;\r
+                                       case STGTY_LOCKBYTES:\r
+                                               fputs("unsupported ILockBytes object - Ignoring & continuing\n",stderr);\r
+                                       break;\r
+                                       case STGTY_PROPERTY:\r
+                                               fputs("unsupported property storage object - Ignoring & continuing\n",stderr);\r
+                                       break;\r
+                                       default:\r
+                                               fputs("unknown object - Ignoring & continuing\n",stderr);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       else fputs("Could not convert the path back to ANSI for the wimpy Win9$ - Ignoring & continuing\n",stderr);\r
+                       delete[]path; path = NULL;\r
+               }\r
+               else fputs("Could not alloc memory for the ANSI pathname for the wimpy Win9$ - Ignoring & continuing\n",stderr);\r
+               CoTaskMemFree(ss.pwcsName); ss.pwcsName = NULL;\r
+       }\r
+       iess->Release();\r
+}\r
+\r
+void fixpath(char* s){\r
+       while(*s){//*s<32 || should probably be removed on non-FAT file systems\r
+               if( *s<32 || strchr(options.invalidchars,*s) )*s=options.fixchar;\r
+               s++;\r
+       }\r
+}
\ No newline at end of file
diff --git a/st2gpx/src/COPYING b/st2gpx/src/COPYING
new file mode 100644 (file)
index 0000000..4567e44
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE\r
+                      Version 2, June 1991\r
+\r
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\r
+                          59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+License is intended to guarantee your freedom to share and change free\r
+software--to make sure the software is free for all its users.  This\r
+General Public License applies to most of the Free Software\r
+Foundation's software and to any other program whose authors commit to\r
+using it.  (Some other Free Software Foundation software is covered by\r
+the GNU Library General Public License instead.)  You can apply it to\r
+your programs, too.\r
+\r
+  When we speak of free software, we are referring to freedom, not\r
+price.  Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+this service if you wish), that you receive source code or can get it\r
+if you want it, that you can change the software or use pieces of it\r
+in new free programs; and that you know you can do these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+anyone to deny you these rights or to ask you to surrender the rights.\r
+These restrictions translate to certain responsibilities for you if you\r
+distribute copies of the software, or if you modify it.\r
+\r
+  For example, if you distribute copies of such a program, whether\r
+gratis or for a fee, you must give the recipients all the rights that\r
+you have.  You must make sure that they, too, receive or can get the\r
+source code.  And you must show them these terms so they know their\r
+rights.\r
+\r
+  We protect your rights with two steps: (1) copyright the software, and\r
+(2) offer you this license which gives you legal permission to copy,\r
+distribute and/or modify the software.\r
+\r
+  Also, for each author's protection and ours, we want to make certain\r
+that everyone understands that there is no warranty for this free\r
+software.  If the software is modified by someone else and passed on, we\r
+want its recipients to know that what they have is not the original, so\r
+that any problems introduced by others will not reflect on the original\r
+authors' reputations.\r
+\r
+  Finally, any free program is threatened constantly by software\r
+patents.  We wish to avoid the danger that redistributors of a free\r
+program will individually obtain patent licenses, in effect making the\r
+program proprietary.  To prevent this, we have made it clear that any\r
+patent must be licensed for everyone's free use or not licensed at all.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.\r
+\f\r
+                   GNU GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License applies to any program or other work which contains\r
+a notice placed by the copyright holder saying it may be distributed\r
+under the terms of this General Public License.  The "Program", below,\r
+refers to any such program or work, and a "work based on the Program"\r
+means either the Program or any derivative work under copyright law:\r
+that is to say, a work containing the Program or a portion of it,\r
+either verbatim or with modifications and/or translated into another\r
+language.  (Hereinafter, translation is included without limitation in\r
+the term "modification".)  Each licensee is addressed as "you".\r
+\r
+Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running the Program is not restricted, and the output from the Program\r
+is covered only if its contents constitute a work based on the\r
+Program (independent of having been made by running the Program).\r
+Whether that is true depends on what the Program does.\r
+\r
+  1. You may copy and distribute verbatim copies of the Program's\r
+source code as you receive it, in any medium, provided that you\r
+conspicuously and appropriately publish on each copy an appropriate\r
+copyright notice and disclaimer of warranty; keep intact all the\r
+notices that refer to this License and to the absence of any warranty;\r
+and give any other recipients of the Program a copy of this License\r
+along with the Program.\r
+\r
+You may charge a fee for the physical act of transferring a copy, and\r
+you may at your option offer warranty protection in exchange for a fee.\r
+\r
+  2. You may modify your copy or copies of the Program or any portion\r
+of it, thus forming a work based on the Program, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) You must cause the modified files to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    b) You must cause any work that you distribute or publish, that in\r
+    whole or in part contains or is derived from the Program or any\r
+    part thereof, to be licensed as a whole at no charge to all third\r
+    parties under the terms of this License.\r
+\r
+    c) If the modified program normally reads commands interactively\r
+    when run, you must cause it, when started running for such\r
+    interactive use in the most ordinary way, to print or display an\r
+    announcement including an appropriate copyright notice and a\r
+    notice that there is no warranty (or else, saying that you provide\r
+    a warranty) and that users may redistribute the program under\r
+    these conditions, and telling the user how to view a copy of this\r
+    License.  (Exception: if the Program itself is interactive but\r
+    does not normally print such an announcement, your work based on\r
+    the Program is not required to print an announcement.)\r
+\f\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Program,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Program, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Program.\r
+\r
+In addition, mere aggregation of another work not based on the Program\r
+with the Program (or with a work based on the Program) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may copy and distribute the Program (or a work based on it,\r
+under Section 2) in object code or executable form under the terms of\r
+Sections 1 and 2 above provided that you also do one of the following:\r
+\r
+    a) Accompany it with the complete corresponding machine-readable\r
+    source code, which must be distributed under the terms of Sections\r
+    1 and 2 above on a medium customarily used for software interchange; or,\r
+\r
+    b) Accompany it with a written offer, valid for at least three\r
+    years, to give any third party, for a charge no more than your\r
+    cost of physically performing source distribution, a complete\r
+    machine-readable copy of the corresponding source code, to be\r
+    distributed under the terms of Sections 1 and 2 above on a medium\r
+    customarily used for software interchange; or,\r
+\r
+    c) Accompany it with the information you received as to the offer\r
+    to distribute corresponding source code.  (This alternative is\r
+    allowed only for noncommercial distribution and only if you\r
+    received the program in object code or executable form with such\r
+    an offer, in accord with Subsection b above.)\r
+\r
+The source code for a work means the preferred form of the work for\r
+making modifications to it.  For an executable work, complete source\r
+code means all the source code for all modules it contains, plus any\r
+associated interface definition files, plus the scripts used to\r
+control compilation and installation of the executable.  However, as a\r
+special exception, the source code distributed need not include\r
+anything that is normally distributed (in either source or binary\r
+form) with the major components (compiler, kernel, and so on) of the\r
+operating system on which the executable runs, unless that component\r
+itself accompanies the executable.\r
+\r
+If distribution of executable or object code is made by offering\r
+access to copy from a designated place, then offering equivalent\r
+access to copy the source code from the same place counts as\r
+distribution of the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\f\r
+  4. You may not copy, modify, sublicense, or distribute the Program\r
+except as expressly provided under this License.  Any attempt\r
+otherwise to copy, modify, sublicense or distribute the Program is\r
+void, and will automatically terminate your rights under this License.\r
+However, parties who have received copies, or rights, from you under\r
+this License will not have their licenses terminated so long as such\r
+parties remain in full compliance.\r
+\r
+  5. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Program or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Program (or any work based on the\r
+Program), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Program or works based on it.\r
+\r
+  6. Each time you redistribute the Program (or any work based on the\r
+Program), the recipient automatically receives a license from the\r
+original licensor to copy, distribute or modify the Program subject to\r
+these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties to\r
+this License.\r
+\r
+  7. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Program at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Program by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Program.\r
+\r
+If any portion of this section is held invalid or unenforceable under\r
+any particular circumstance, the balance of the section is intended to\r
+apply and the section as a whole is intended to apply in other\r
+circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system, which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\f\r
+  8. If the distribution and/or use of the Program is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Program under this License\r
+may add an explicit geographical distribution limitation excluding\r
+those countries, so that distribution is permitted only in or among\r
+countries not thus excluded.  In such case, this License incorporates\r
+the limitation as if written in the body of this License.\r
+\r
+  9. The Free Software Foundation may publish revised and/or new versions\r
+of the General Public License from time to time.  Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Program\r
+specifies a version number of this License which applies to it and "any\r
+later version", you have the option of following the terms and conditions\r
+either of that version or of any later version published by the Free\r
+Software Foundation.  If the Program does not specify a version number of\r
+this License, you may choose any version ever published by the Free Software\r
+Foundation.\r
+\r
+  10. If you wish to incorporate parts of the Program into other free\r
+programs whose distribution conditions are different, write to the author\r
+to ask for permission.  For software which is copyrighted by the Free\r
+Software Foundation, write to the Free Software Foundation; we sometimes\r
+make exceptions for this.  Our decision will be guided by the two goals\r
+of preserving the free status of all derivatives of our free software and\r
+of promoting the sharing and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\r
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\r
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\r
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\r
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r
+REPAIR OR CORRECTION.\r
+\r
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
+\f\r
+       Appendix: How to Apply These Terms to Your New Programs\r
+\r
+  If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+\r
+  To do so, attach the following notices to the program.  It is safest\r
+to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the program's name and a brief idea of what it does.>\r
+    Copyright (C) 19yy  <name of author>\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+If the program is interactive, make it output a short notice like this\r
+when it starts in an interactive mode:\r
+\r
+    Gnomovision version 69, Copyright (C) 19yy name of author\r
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+    This is free software, and you are welcome to redistribute it\r
+    under certain conditions; type `show c' for details.\r
+\r
+The hypothetical commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License.  Of course, the commands you use may\r
+be called something other than `show w' and `show c'; they could even be\r
+mouse-clicks or menu items--whatever suits your program.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the program, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1989\r
+  Ty Coon, President of Vice\r
+\r
+This General Public License does not permit incorporating your program into\r
+proprietary programs.  If your program is a subroutine library, you may\r
+consider it more useful to permit linking proprietary applications with the\r
+library.  If this is what you want to do, use the GNU Library General\r
+Public License instead of this License.\r
diff --git a/st2gpx/src/getopt.c b/st2gpx/src/getopt.c
new file mode 100644 (file)
index 0000000..59b51cd
--- /dev/null
@@ -0,0 +1,1050 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
+       Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+\f
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#include <unistd.h>
+#endif /* GNU C library.  */
+
+#ifdef VMS
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
+#endif
+
+#if defined (WIN32) && !defined (__CYGWIN32__)
+/* It's not Unix, really.  See?  Capital letters.  */
+#include <windows.h>
+#define getpid() GetCurrentProcessId()
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+   When compiling libc, the _ macro is predefined.  */
+#ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid)      gettext (msgid)
+#else
+# define _(msgid)      (msgid)
+#endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+   causes problems with re-calling getopt as programs generally don't
+   know that. */
+
+int __getopt_initialized = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+\f
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define        my_index        strchr
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+       return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+\f
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+extern pid_t __libc_pid;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+   is valid for the getopt call we must make sure that the ARGV passed
+   to getopt is that one passed to the process.  */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+  /* XXX This is no good solution.  We should rather copy the args so
+     that we can compare them later.  But we must not use malloc(3).  */
+  original_argc = argc;
+  original_argv = argv;
+}
+text_set_element (__libc_subinit, store_args_and_env);
+
+# define SWAP_FLAGS(ch1, ch2) \
+  if (nonoption_flags_len > 0)                                               \
+    {                                                                        \
+      char __tmp = __getopt_nonoption_flags[ch1];                            \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];         \
+      __getopt_nonoption_flags[ch2] = __tmp;                                 \
+    }
+#else  /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+#if defined (__STDC__) && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#ifdef _LIBC
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+        presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+       nonoption_flags_len = nonoption_flags_max_len = 0;
+      else
+       {
+         memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
+         memset (&new_str[nonoption_flags_max_len], '\0',
+                 top + 1 - nonoption_flags_max_len);
+         nonoption_flags_max_len = top + 1;
+         __getopt_nonoption_flags = new_str;
+       }
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+       {
+         /* Bottom segment is the short one.  */
+         int len = middle - bottom;
+         register int i;
+
+         /* Swap it with the top part of the top segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[top - (middle - bottom) + i];
+             argv[top - (middle - bottom) + i] = tem;
+             SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+           }
+         /* Exclude the moved bottom segment from further swapping.  */
+         top -= len;
+       }
+      else
+       {
+         /* Top segment is the short one.  */
+         int len = top - middle;
+         register int i;
+
+         /* Swap it with the bottom part of the bottom segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[middle + i];
+             argv[middle + i] = tem;
+             SWAP_FLAGS (bottom + i, middle + i);
+           }
+         /* Exclude the moved top segment from further swapping.  */
+         bottom += len;
+       }
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+#if defined (__STDC__) && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind;
+
+  nextchar = NULL;
+
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (posixly_correct != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+#ifdef _LIBC
+  if (posixly_correct == NULL
+      && argc == original_argc && argv == original_argv)
+    {
+      if (nonoption_flags_max_len == 0)
+       {
+         if (__getopt_nonoption_flags == NULL
+             || __getopt_nonoption_flags[0] == '\0')
+           nonoption_flags_max_len = -1;
+         else
+           {
+             const char *orig_str = __getopt_nonoption_flags;
+             int len = nonoption_flags_max_len = strlen (orig_str);
+             if (nonoption_flags_max_len < argc)
+               nonoption_flags_max_len = argc;
+             __getopt_nonoption_flags =
+               (char *) malloc (nonoption_flags_max_len);
+             if (__getopt_nonoption_flags == NULL)
+               nonoption_flags_max_len = -1;
+             else
+               {
+                 memcpy (__getopt_nonoption_flags, orig_str, len);
+                 memset (&__getopt_nonoption_flags[len], '\0',
+                         nonoption_flags_max_len - len);
+               }
+           }
+       }
+      nonoption_flags_len = nonoption_flags_max_len;
+    }
+  else
+    nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  optarg = NULL;
+
+  if (optind == 0 || !__getopt_initialized)
+    {
+      if (optind == 0)
+       optind = 1;     /* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring);
+      __getopt_initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#ifdef _LIBC
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'       \
+                    || (optind < nonoption_flags_len                         \
+                        && __getopt_nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+        moved back by the user (who may also have changed the arguments).  */
+      if (last_nonopt > optind)
+       last_nonopt = optind;
+      if (first_nonopt > optind)
+       first_nonopt = optind;
+
+      if (ordering == PERMUTE)
+       {
+         /* If we have just processed some options following some non-options,
+            exchange them so that the options come first.  */
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (last_nonopt != optind)
+           first_nonopt = optind;
+
+         /* Skip any additional non-options
+            and extend the range of non-options previously skipped.  */
+
+         while (optind < argc && NONOPTION_P)
+           optind++;
+         last_nonopt = optind;
+       }
+
+      /* The special ARGV-element `--' means premature end of options.
+        Skip it like a null option,
+        then exchange with previous non-options as if it were an option,
+        then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+       {
+         optind++;
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (first_nonopt == last_nonopt)
+           first_nonopt = optind;
+         last_nonopt = argc;
+
+         optind = argc;
+       }
+
+      /* If we have done all the ARGV-elements, stop the scan
+        and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+       {
+         /* Set the next-arg-index to point at the non-options
+            that we previously skipped, so the caller will digest them.  */
+         if (first_nonopt != last_nonopt)
+           optind = first_nonopt;
+         return -1;
+       }
+
+      /* If we have come to a non-option and did not permute it,
+        either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+       {
+         if (ordering == REQUIRE_ORDER)
+           return -1;
+         optarg = argv[optind++];
+         return 1;
+       }
+
+      /* We have found another option-ARGV-element.
+        Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+                 + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+         || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+       /* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+        or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+       if (!strncmp (p->name, nextchar, nameend - nextchar))
+         {
+           if ((unsigned int) (nameend - nextchar)
+               == (unsigned int) strlen (p->name))
+             {
+               /* Exact match found.  */
+               pfound = p;
+               indfound = option_index;
+               exact = 1;
+               break;
+             }
+           else if (pfound == NULL)
+             {
+               /* First nonexact match found.  */
+               pfound = p;
+               indfound = option_index;
+             }
+           else
+             /* Second or later nonexact match found.  */
+             ambig = 1;
+         }
+
+      if (ambig && !exact)
+       {
+         if (opterr)
+           fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+                    argv[0], argv[optind]);
+         nextchar += strlen (nextchar);
+         optind++;
+         optopt = 0;
+         return '?';
+       }
+
+      if (pfound != NULL)
+       {
+         option_index = indfound;
+         optind++;
+         if (*nameend)
+           {
+             /* Don't test has_arg with >, because some C compilers don't
+                allow it to be used on enums.  */
+             if (pfound->has_arg)
+               optarg = nameend + 1;
+             else
+               {
+                 if (opterr)
+                  if (argv[optind - 1][1] == '-')
+                   /* --option */
+                   fprintf (stderr,
+                    _("%s: option `--%s' doesn't allow an argument\n"),
+                    argv[0], pfound->name);
+                  else
+                   /* +option or -option */
+                   fprintf (stderr,
+                    _("%s: option `%c%s' doesn't allow an argument\n"),
+                    argv[0], argv[optind - 1][0], pfound->name);
+
+                 nextchar += strlen (nextchar);
+
+                 optopt = pfound->val;
+                 return '?';
+               }
+           }
+         else if (pfound->has_arg == 1)
+           {
+             if (optind < argc)
+               optarg = argv[optind++];
+             else
+               {
+                 if (opterr)
+                   fprintf (stderr,
+                          _("%s: option `%s' requires an argument\n"),
+                          argv[0], argv[optind - 1]);
+                 nextchar += strlen (nextchar);
+                 optopt = pfound->val;
+                 return optstring[0] == ':' ? ':' : '?';
+               }
+           }
+         nextchar += strlen (nextchar);
+         if (longind != NULL)
+           *longind = option_index;
+         if (pfound->flag)
+           {
+             *(pfound->flag) = pfound->val;
+             return 0;
+           }
+         return pfound->val;
+       }
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+        or the option starts with '--' or is not a valid short
+        option, then it's an error.
+        Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+         || my_index (optstring, *nextchar) == NULL)
+       {
+         if (opterr)
+           {
+             if (argv[optind][1] == '-')
+               /* --option */
+               fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+                        argv[0], nextchar);
+             else
+               /* +option or -option */
+               fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+                        argv[0], argv[optind][0], nextchar);
+           }
+         nextchar = (char *) "";
+         optind++;
+         optopt = 0;
+         return '?';
+       }
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+       if (opterr)
+         {
+           if (posixly_correct)
+             /* 1003.2 specifies the format of this message.  */
+             fprintf (stderr, _("%s: illegal option -- %c\n"),
+                      argv[0], c);
+           else
+             fprintf (stderr, _("%s: invalid option -- %c\n"),
+                      argv[0], c);
+         }
+       optopt = c;
+       return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+       char *nameend;
+       const struct option *p;
+       const struct option *pfound = NULL;
+       int exact = 0;
+       int ambig = 0;
+       int indfound = 0;
+       int option_index;
+
+       /* This is an option that requires an argument.  */
+       if (*nextchar != '\0')
+         {
+           optarg = nextchar;
+           /* If we end this ARGV-element by taking the rest as an arg,
+              we must advance to the next element now.  */
+           optind++;
+         }
+       else if (optind == argc)
+         {
+           if (opterr)
+             {
+               /* 1003.2 specifies the format of this message.  */
+               fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+                        argv[0], c);
+             }
+           optopt = c;
+           if (optstring[0] == ':')
+             c = ':';
+           else
+             c = '?';
+           return c;
+         }
+       else
+         /* We already incremented `optind' once;
+            increment it again when taking next ARGV-elt as argument.  */
+         optarg = argv[optind++];
+
+       /* optarg is now the argument, see if it's in the
+          table of longopts.  */
+
+       for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+         /* Do nothing.  */ ;
+
+       /* Test all long options for either exact match
+          or abbreviated matches.  */
+       for (p = longopts, option_index = 0; p->name; p++, option_index++)
+         if (!strncmp (p->name, nextchar, nameend - nextchar))
+           {
+             if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+               {
+                 /* Exact match found.  */
+                 pfound = p;
+                 indfound = option_index;
+                 exact = 1;
+                 break;
+               }
+             else if (pfound == NULL)
+               {
+                 /* First nonexact match found.  */
+                 pfound = p;
+                 indfound = option_index;
+               }
+             else
+               /* Second or later nonexact match found.  */
+               ambig = 1;
+           }
+       if (ambig && !exact)
+         {
+           if (opterr)
+             fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+                      argv[0], argv[optind]);
+           nextchar += strlen (nextchar);
+           optind++;
+           return '?';
+         }
+       if (pfound != NULL)
+         {
+           option_index = indfound;
+           if (*nameend)
+             {
+               /* Don't test has_arg with >, because some C compilers don't
+                  allow it to be used on enums.  */
+               if (pfound->has_arg)
+                 optarg = nameend + 1;
+               else
+                 {
+                   if (opterr)
+                     fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+                              argv[0], pfound->name);
+
+                   nextchar += strlen (nextchar);
+                   return '?';
+                 }
+             }
+           else if (pfound->has_arg == 1)
+             {
+               if (optind < argc)
+                 optarg = argv[optind++];
+               else
+                 {
+                   if (opterr)
+                     fprintf (stderr,
+                              _("%s: option `%s' requires an argument\n"),
+                              argv[0], argv[optind - 1]);
+                   nextchar += strlen (nextchar);
+                   return optstring[0] == ':' ? ':' : '?';
+                 }
+             }
+           nextchar += strlen (nextchar);
+           if (longind != NULL)
+             *longind = option_index;
+           if (pfound->flag)
+             {
+               *(pfound->flag) = pfound->val;
+               return 0;
+             }
+           return pfound->val;
+         }
+         nextchar = NULL;
+         return 'W';   /* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+       if (temp[2] == ':')
+         {
+           /* This is an option that accepts an argument optionally.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               optind++;
+             }
+           else
+             optarg = NULL;
+           nextchar = NULL;
+         }
+       else
+         {
+           /* This is an option that requires an argument.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               /* If we end this ARGV-element by taking the rest as an arg,
+                  we must advance to the next element now.  */
+               optind++;
+             }
+           else if (optind == argc)
+             {
+               if (opterr)
+                 {
+                   /* 1003.2 specifies the format of this message.  */
+                   fprintf (stderr,
+                          _("%s: option requires an argument -- %c\n"),
+                          argv[0], c);
+                 }
+               optopt = c;
+               if (optstring[0] == ':')
+                 c = ':';
+               else
+                 c = '?';
+             }
+           else
+             /* We already incremented `optind' once;
+                increment it again when taking next ARGV-elt as argument.  */
+             optarg = argv[optind++];
+           nextchar = NULL;
+         }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+                          (const struct option *) 0,
+                          (int *) 0,
+                          0);
+}
+
+#endif /* Not ELIDE_CODE.  */
+\f
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+       break;
+
+      switch (c)
+       {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/st2gpx/src/getopt.h b/st2gpx/src/getopt.h
new file mode 100644 (file)
index 0000000..a0fe18a
--- /dev/null
@@ -0,0 +1,131 @@
+/* Declarations for getopt.
+   Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument         (or 0) if the option does not take an argument,
+   required_argument   (or 1) if the option requires an argument,
+   optional_argument   (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define        no_argument             0
+#define required_argument      1
+#define optional_argument      2
+
+//#if defined (__STDC__) && __STDC__
+//#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+//#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+//#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+                       const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind,
+                            int long_only);
+//#else /* not __STDC__ */
+//extern int getopt ();
+//extern int getopt_long ();
+//extern int getopt_long_only ();
+
+//extern int _getopt_internal ();
+//#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/st2gpx/src/pushpins.cpp b/st2gpx/src/pushpins.cpp
new file mode 100644 (file)
index 0000000..2143019
--- /dev/null
@@ -0,0 +1,224 @@
+/*\r
+       pushpins.cpp\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+*/\r
+\r
+#import "c:\program files\common files\system\ado\msado15.dll" rename ( "EOF", "adoEOF" )\r
+//#import <msado15.dll> rename ( "EOF", "adoEOF" )\r
+\r
+#include <windows.h>\r
+#include <initguid.h>  // Include only once in your application\r
+//#include "adoid.h"     // ADO GUID's\r
+//#include "adoint.h"    // ADO Classes, enums, etc.\r
+#include <oleauto.h>   // for sysstringlength\r
+#include <stdio.h>\r
+//#include <stdlib.h>\r
+//#include <malloc.h>\r
+//#include <memory.h>\r
+#include <string.h>\r
+\r
+#include "pushpins.h"\r
+\r
+struct InitOle {\r
+InitOle()  { ::CoInitialize(NULL); }\r
+~InitOle() { ::CoUninitialize();   }\r
+} _init_InitOle_;\r
+\r
+int verbose_flag;\r
+\r
+void * xmalloc(size_t size)\r
+{\r
+       void *obj = malloc(size);\r
+       if (!obj)\r
+       {\r
+               fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size);\r
+       }\r
+       return obj;\r
+}\r
+\r
+LPWSTR wstr2cpy(BSTR wstr)\r
+{\r
+       int len=wcslen(wstr);\r
+       LPWSTR newstr=(LPWSTR)xmalloc((len+1)*sizeof(WCHAR));\r
+       wcscpy(newstr, wstr);\r
+       return newstr;\r
+}\r
+\r
+char* wstr2str(BSTR wstr)\r
+// there must be a better way to do this\r
+{\r
+       int len;\r
+       int i;\r
+       char* newstr=NULL;\r
+       // call to get length\r
+       len = WideCharToMultiByte(\r
+                               CP_THREAD_ACP,\r
+                               0,\r
+                               wstr,\r
+                               -1,\r
+                               newstr,\r
+                               0, \r
+                               NULL,\r
+                               0);\r
+       if(len==0)\r
+       {\r
+               //printf("wide2normal got length %d\n", len);\r
+               len=wcslen(wstr);\r
+               //printf("wide2normal cheated and got length %d\n", len);\r
+       };\r
+       newstr = (char*)xmalloc((len+1)*sizeof(char));\r
+       // now call to set string\r
+       len = WideCharToMultiByte(\r
+                               CP_THREAD_ACP,\r
+                               0,\r
+                               wstr,\r
+                               -1,\r
+                               newstr,\r
+                               len, \r
+                               NULL,\r
+                               0);\r
+       //printf("wide2normal copied %d chars and got string %s\n", len, newstr);\r
+       if (len==0)\r
+       {\r
+               len=wcslen(wstr);\r
+               for(i=0; i<len; i++)\r
+                       newstr[i]=wstr[i];\r
+               newstr[len]=0;\r
+               //printf("wide2normal cheated to get string %s\n", newstr);\r
+       }\r
+       return newstr;\r
+}\r
+\r
+void readfield(VARIANT vt_val, unsigned short fieldtype, void* stor_var)\r
+{\r
+//     int len=0;\r
+       LPWSTR tempwstr=NULL;\r
+       char* shortstr=NULL;\r
+//     int status;\r
+//     int i;\r
+\r
+       if ((vt_val.vt == fieldtype) || ( (fieldtype==VT_BSTR) && (vt_val.vt==VT_NULL)))\r
+       {\r
+               switch (vt_val.vt)\r
+               {\r
+               case VT_I4:\r
+                       *(long*)stor_var = vt_val.lVal;\r
+                       break;\r
+\r
+               case VT_I2:\r
+                       *(int*)stor_var = vt_val.iVal;\r
+                       break;\r
+\r
+               case VT_BSTR:\r
+                       // FIXME handle bstr properly\r
+                       tempwstr = wstr2cpy(vt_val.bstrVal);\r
+                       //wprintf(L"got temp str%s\n",tempwstr);\r
+\r
+                       shortstr = wstr2str(vt_val.bstrVal);\r
+                       //printf("got short temp str%s\n",shortstr);\r
+                       \r
+                       //*(void**)stor_var = (void*)tempwstr;\r
+                       *(char**)stor_var = shortstr;\r
+                       //printf("verified short temp str%s\n", *(char**)stor_var);\r
+                       break;\r
+\r
+               case VT_NULL:\r
+                       // expected string, this is null \r
+                       // so return empty string\r
+\r
+                       shortstr = (char*)xmalloc(sizeof(char));\r
+                       shortstr[0]=0;\r
+                       //printf("got short temp str%s\n",shortstr);\r
+                       \r
+                       *(char**)stor_var = shortstr;\r
+                       break;\r
+               default:\r
+                       fprintf(stderr,"Unsupported type, unable to read from DB\n");\r
+               }\r
+\r
+       }\r
+       else\r
+       {\r
+               fprintf(stderr,"Type mismatch when reading from DB, expected type %d read type %d\n", \r
+                       fieldtype, vt_val.vt);\r
+       }\r
+\r
+}\r
+\r
+// EXTERN_C \r
+EXTERN_C void read_ppin_list(char* ppin_file_name)\r
+{\r
+\r
+       struct pushpin * ppin;\r
+       int ppinnum=0;\r
+       \r
+       try \r
+       {\r
+               HRESULT hr = S_OK;\r
+               ADODB::_RecordsetPtr rs; \r
+               char cnstr[500];\r
+               char sqlstr[] = "SELECT UD_Secondary.UdId, UD_Secondary.UdName, UD_Secondary.NoteShort, UD_Secondary.NoteLong, UD_Main.Grid, UD_Main.Precision FROM UD_Main INNER JOIN UD_Secondary ON UD_Main.UdId = UD_Secondary.UdId";\r
+               sprintf(cnstr, "PROVIDER=Microsoft.Jet.OLEDB.4.0;data source=%s; Jet OLEDB:Database Password=Geo80;", ppin_file_name);\r
+\r
+               hr = rs.CreateInstance( __uuidof( ADODB::Recordset ) );\r
+               hr = rs->Open(sqlstr, \r
+                                 cnstr, \r
+                                         ADODB::adOpenForwardOnly, \r
+                                         ADODB::adLockReadOnly, \r
+                                         -1 );\r
+               hr = rs->MoveFirst();\r
+               while ((rs->adoEOF == FALSE))\r
+               {\r
+                       ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin));\r
+\r
+                       readfield(rs->Fields->GetItem("UdId")->Value,           VT_I4,  &(ppin->UdId));\r
+                       readfield(rs->Fields->GetItem("UdName")->Value,         VT_BSTR,&(ppin->UdName));\r
+                       readfield(rs->Fields->GetItem("Grid")->Value,           VT_I4,  &(ppin->Grid));\r
+                       readfield(rs->Fields->GetItem("Precision")->Value,      VT_I4,  &(ppin->Precision));\r
+                       readfield(rs->Fields->GetItem("NoteShort")->Value,      VT_BSTR,&(ppin->NoteShort));\r
+\r
+                       if (verbose_flag > 3)\r
+                               printf("Read pushpin UdId=%d, UdName=%s, Grid=%d, Precision=%d, NoteShort=%s\n", \r
+                                       ppin->UdId, ppin->UdName, \r
+                                       ppin->Grid, ppin->Precision, ppin->NoteShort);\r
+\r
+                       ppin_list[ppinnum]=ppin;\r
+                       ppinnum++;\r
+                       if (ppinnum>MAX_PUSHPINS-1)\r
+                       {\r
+                               printf("Exceeded maximun number of pushpins (I should fix this)\n");\r
+                               break;\r
+                       }\r
+\r
+                       hr = rs->MoveNext();\r
+               }\r
+               hr = rs->Close();\r
+               rs = NULL;\r
+       }\r
+       catch( _com_error &e)\r
+       {\r
+        _bstr_t bstrSource(e.Source());\r
+        _bstr_t bs =  _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") \r
+            + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") \r
+            + _bstr_t(e.Description());\r
+        \r
+        MessageBox(0,bs,bstrSource, MB_OK);\r
+    }  \r
+}\r
diff --git a/st2gpx/src/pushpins.h b/st2gpx/src/pushpins.h
new file mode 100644 (file)
index 0000000..e699a40
--- /dev/null
@@ -0,0 +1,96 @@
+/*\r
+       pushpins.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+*/\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define MAX_PUSHPINS 5000\r
+\r
+// max size to be read from ppin memo fields\r
+#define MAX_PPIN_MEMO  1000\r
+\r
+typedef struct pushpin\r
+{\r
+       long UdId;\r
+       int SetId;\r
+       long Grid;\r
+       long Precision;\r
+//     dword RenderData;\r
+//     byte MatchId;\r
+//     long MOBBId;\r
+//     long SourceUdId;\r
+//     bool IsTerritory;\r
+//\r
+       char* UdName;   // max 128\r
+//     bool NoNameSearch;\r
+//     byte NoteTypeId;\r
+       char* NoteShort; // max 255\r
+//     char* NoteLong; // memo\r
+//     char* GeocodeShort; // max 255\r
+//     char* GeocodeLong; // memo\r
+//     byte GeocodeHierarchy; \r
+//     byte GeocodeContext; \r
+//     OLE Object EntityArray ????\r
+//\r
+// shouldn't include these two here because they are not part of the native pushpin definition\r
+       double lat;\r
+       double lon;\r
+} tag_pushpin;\r
+\r
+\r
+typedef struct pushpinset\r
+{\r
+       int SetId;\r
+       char* SetName; // max 128\r
+/*     byte RenderMethod;\r
+       byte GeocodeMethod;\r
+       byte CreateMethod;\r
+       byte GeometryType;\r
+       char[128] RenderData;\r
+       long UdCount;\r
+       long MatchedCount;\r
+       long SkippedCount;\r
+       long UnmatchedCount;\r
+       long CounterUpdateMask;\r
+       int ParentSetId;\r
+       bool IsRendered;\r
+       long Z_Order;\r
+       long GeocodeCtxt;\r
+       OLE Object ThemeRenderData\r
+       date/time LastGeocoded\r
+       char* DataSrcDescr; // memo\r
+       char[30] CurrencyData;\r
+*/\r
+} tag_pushpinset;\r
+\r
+//struct pushpin * ppin_list[MAX_PUSHPINS];\r
+struct pushpin * ppin_list[5000];\r
+\r
+//EXTERN_C\r
+ void read_ppin_list(char* ppin_file_name);\r
+\r
+\r
+#ifdef __cplusplus\r
+} /* closing brace for extern "C" */\r
+#endif\r
diff --git a/st2gpx/src/st2gpx.c b/st2gpx/src/st2gpx.c
new file mode 100644 (file)
index 0000000..8b5c17a
--- /dev/null
@@ -0,0 +1,1523 @@
+/*\r
+       st2gpxmain.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+History:\r
+\r
+21-10-2003     annotations stream dump\r
+27-10-2003     journey & pushpins using VB module\r
+ 8-11-2003     match journey route-points to pushpins,\r
+                       integrate parts into singel C/C++ exe (except istorage)\r
+ 9-11-2003  fixed invalid gpx\r
+\r
+To do:\r
+       Get lat & lon for journey route points not matched to pushpins\r
+       Get point info for non-line annotations, e.g. text boxes.\r
+       Import functionality\r
+       Implement using platform independant libraries.\r
+\r
+bugs:\r
+       unable to delete UserData file after accessing with ADO.\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <memory.h>\r
+#include <math.h>\r
+#include <string.h>\r
+\r
+// #include <getopt.h>\r
+#include "getopt.h"\r
+#include "pushpins.h"\r
+\r
+#ifndef M_PI\r
+#define M_PI 3.1415926535\r
+#endif\r
+\r
+#define JOUR_FILE_HEAD_LEN 32\r
+#define JOUR_FILE_TAIL_LEN 430\r
+// + text1 +2*text2\r
+#define JOUR_WPTREC_LEN 121\r
+\r
+#define JOUR_FILEOS_NUMREC 16\r
+\r
+#define JOURWPT_REC_HEAD_LEN 41\r
+\r
+#define JOURWPT_RECOS_WPTNUM 0\r
+#define JOURWPT_RECOS_STR1LEN 40\r
+#define JOURWPT_RECOS_STR1 41\r
+// + val(JOURWPT_RECOS_STR1LEN)\r
+#define JOURWPT_RECOS_STR2LEN 44\r
+#define JOURWPT_RECOS_STR2 45\r
+\r
+#define ANNOT_FILE_HEAD_LEN 12\r
+// This needs to be long enough to get enough params to decide which record,\r
+// but no biger than the shortest record\r
+#define ANNOT_REC_HEAD_LEN 57 //19\r
+\r
+#define ANNOT_TYPE_LINE                0\r
+#define ANNOT_TYPE_OVAL                1\r
+#define ANNOT_TYPE_TEXT                2\r
+#define ANNOT_TYPE_CIRCLE      3\r
+\r
+#define REC_CLOSE_LEN 0\r
+// offsets for parameters in annotation recods\r
+#define ANNOT_RECOS_TYPE       0\r
+#define ANNOT_RECOS_ANUM       4\r
+#define ANNOT_RECOS_TEXTLEN    20\r
+#define ANNOT_RECOS_TEXT       24\r
+#define ANNOT_RECOS_LINENUMPOINTS 53\r
+#define ANNOT_RECOS_LINEJOINFLAG 48\r
+#define ANNOT_RECOS_XSCALE     48\r
+#define ANNOT_RECOS_YSCALE     52\r
+\r
+#define GPX_HEADER1 "<?xml version=\"1.0\" standalone=\"yes\"?>\n<gpx version=\"1.0\" \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xmlns=\"http://www.topografix.com/GPX/1/0\"\n  xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\"\n "\r
+#define GPX_HEADER2 " creator=\"st2gpx-james_sherring@yahoo.com\">\n"\r
+#define GPX_THIS_PROGRAM "st2gpx from james_sherring@yahoo.com"\r
+#define GPX_FOOTER "</gpx>"\r
+\r
+#define GPX_WPT 0\r
+#define GPX_RTEPT 1\r
+#define GPX_TRKPT 2\r
+\r
+/*\r
+typedef struct annotationbuf\r
+{\r
+       int annot_num;\r
+       int flags;              // bit fields in first byte\r
+       int unkn1;              // normally 0\r
+       int unkn2;              // ? seems to have byte fields\r
+       int text_len;\r
+       // + 2*text_len bytes of text here\r
+       int fill_color; // seems to have byte fields. First byte is fill, other bytes are strange\r
+       int line_color;\r
+       int line_thickness; // 20 times the point-size\r
+       int arrow_type;         // 00=none, 01=left, 02=right, 03=both\r
+       int unkn3;\r
+       int joinflag;           // 0 line does not join, 1, joins. Not sure what large balues for non-lines mean - xscale?\r
+       char unkn4;                     // y-scale?\r
+       int num_points;         // different meaning for non-lines\r
+} structannotationbuf;\r
+*/\r
+\r
+typedef struct jourwpt_rec\r
+{\r
+       int jour_num;\r
+       int text1_length;\r
+       char* text1;\r
+       int text2_length;\r
+       char* text2;\r
+       long UdId;\r
+       struct pushpin* pushpin;\r
+       int buf_length;\r
+       char* buf;\r
+} tag_jour_rec;\r
+\r
+typedef struct gpx_point\r
+{\r
+       float lat;\r
+       float lon;\r
+       float height;\r
+} tag_gpx_point;\r
+\r
+typedef char* annot_file_header;\r
+typedef char* annot_rec_header;\r
+typedef char* annot_buf;\r
+\r
+typedef struct annot_rec\r
+{\r
+       int type;\r
+       int length;\r
+       char* buf;\r
+       int annot_num;\r
+       int text_length;\r
+       char* text;\r
+       int line_points;\r
+} tag_annot_rec;\r
+\r
+struct point {\r
+       double lon;\r
+       double lat;\r
+} tag_point;\r
+\r
+struct ms_point {\r
+       long grid;\r
+       long precision;\r
+} tag_ms_point;\r
+\r
+\r
+// Also need to include variable text length + line-points with these\r
+int annot_rec_len[4]={57, 868, 124, 868};\r
+int annot_head_len[4]={57, 48, 48, 48};\r
+char* annot_type_name[4]={"Line", "Oval", "Textbox", "Circle"};\r
+static char* gpxptypelabel[] = {"wpt", "rtept", "trkpt"};\r
+\r
+// constants for converting from MS Grid & Precision to latitude and longitude\r
+double magic1 = 182.044444444444;\r
+double magic2 = 0x10000;\r
+\r
+// Args set by getopt etc\r
+\r
+FILE* ppin_file=NULL;\r
+FILE* jour_file=NULL;\r
+FILE* annot_file=NULL;\r
+FILE* gpx_file=NULL;\r
+char* source_file_name=NULL;\r
+\r
+/* Flag set by --verbose. */\r
+// 0 - only errors\r
+// 1 also the structured data output, e.g. line point info\r
+// 2 also record types & parameters\r
+// 3 also detailed summary info\r
+// 4 also detailed analysis of headers & record params\r
+// 5 also dump buffers\r
+// 6 lots of debug info\r
+static int verbose_flag = 2;\r
+static int explore_flag = 0;\r
+// force line-type annotations to be exported as GPX routes instead of tracks\r
+static int use_gpx_route = 0;\r
+\r
+// std_anotfile_header[8,9] are variable (number of annotations)\r
+char std_annotfile_header[ANNOT_FILE_HEAD_LEN] =\r
+                       {0x34, 0x12, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};\r
+\r
+void * xmalloc(size_t size)\r
+{\r
+       void *obj = malloc(size);\r
+       if (!obj)\r
+       {\r
+               fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size);\r
+       }\r
+       return obj;\r
+}\r
+\r
+void * xrealloc(void* ptr, size_t size)\r
+{\r
+       void *obj = realloc(ptr, size);\r
+       if (!obj)\r
+       {\r
+               fprintf(stderr, "Unable to (re)allocate %d bytes of memory.\n", size);\r
+       }\r
+       return obj;\r
+}\r
+\r
+int fixhex(char c)\r
+{\r
+// gcc (version?) does not print single byte hex vaues properly\r
+// eg 0xe3 prints as 0xFFFFFFE3\r
+// this is only a problem for values above 0x80\r
+// Or maybe that is the proper handling of unsigned?\r
+// Aaaahhh. I should use %u for printing unsigned... but the hex problem is still there\r
+       if(c & 0x80)\r
+       {\r
+               return ((int)c-0xFFFFFF00);\r
+       } else\r
+               return c;\r
+}\r
+\r
+void printbuf(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+       printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+       printf("    -----------------------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               if (((i+1) & 0x0f) == 0x1)\r
+                       printf("\n%2x| ",i/16);\r
+               printf("%2x ",fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufwide(char* buf, int len)\r
+{\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("%2x ",fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufhigh(char* buf, int len)\r
+{\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("%02x %02x\n", i, fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufasfloat(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+//     printf("    -----------------------------------------------");\r
+       for(i=0; i<len-3; i++)\r
+       {\r
+               if (((i+1) & 0x03) == 0x1)\r
+                       printf("\n%2x| ",i);\r
+               printf("%f  ", *(float*)(buf+i));\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printfloatbuf(float* fbuf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+//     printf("    -----------------------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               if (((i+1) & 0x03) == 0x1)\r
+                       printf("\n%2x| ",4*i);\r
+               printf("%f  ", fbuf[i]);\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+struct gpx_point gpx_get_point(char* buf)\r
+{\r
+// need to be sure this is done with double precision\r
+       struct gpx_point pt;\r
+       double x;\r
+       double y;\r
+       double z;\r
+\r
+       x= *(float *)(buf);\r
+       y= *(float *)(buf + 4);\r
+       z= *(float *)(buf + 8);\r
+\r
+       //printf("gpx_get_point x=%f y=%f z=%f\n",x,y,z);\r
+       pt.lat =  atan2(z,sqrt(pow(x,2)+ pow(y,2)))*180/M_PI;\r
+       pt.lon =  atan2(y,x)*180/M_PI;\r
+       // 6378137 is earths equatorial radius in meters\r
+       pt.height = (sqrt(pow(x,2)+ pow(y,2)+ pow(z,2))-1)*6378137;\r
+       return pt;\r
+}\r
+\r
+void printpoints(char* buf, int numpts)\r
+{\r
+       int i;\r
+//     int j;\r
+       struct gpx_point pt;\r
+       printf("Latitude  Longitude Height");\r
+       printf("\n");\r
+       printf("--------------------------\n");\r
+       for(i=0; i<numpts; i++)\r
+       {\r
+               pt = gpx_get_point(buf + 12*i);\r
+               printf("%f %f %f \n",pt.lat, pt.lon, pt.height);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printpointsbuf(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+//     unsigned j;\r
+       int i;\r
+       int j;\r
+       printf("     0  1  2  3  4  5  6  7  8  9  A  B\n");\r
+       printf("    -----------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("\n%2x| ",i);\r
+       //      printf("\n");\r
+               for (j=0; j<12; j++)\r
+               {\r
+                       printf("%2x ",fixhex(buf[12*i+j]));\r
+                       fflush(stdout);\r
+               }\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufaspoints(char* buf, int buflen)\r
+{\r
+       int i;\r
+//     int j;\r
+       struct gpx_point pt;\r
+       printf("Latitude  Longitude Height");\r
+       printf("\n");\r
+       printf("--------------------------\n");\r
+       for(i=0; i<buflen-11; i++)\r
+       {\r
+               pt = gpx_get_point(buf + 12*i);\r
+               printf("%#02x %f N %f E %f m \n", i, pt.lat, pt.lon, pt.height);\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printnzbuf(char* buf, int len)\r
+{\r
+// print non-zero values in the buffer\r
+//     unsigned i;\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+//             if (buf[i] != 0) printf("Buf[%x]=%2x ",fixhex(i), fixhex(buf[i]));\r
+               if (buf[i] != 0) printf("Buf[%x]=%2x ",i, fixhex(buf[i]));\r
+       }\r
+       printf("\n");\r
+}\r
+\r
+void printnzhead(struct annot_rec rec)\r
+{\r
+       printnzbuf(rec.buf, annot_head_len[rec.type]);\r
+}\r
+\r
+struct point ms2latlong(struct ms_point msp) {\r
+\r
+// grid and precision are the high and low words obtained by interleaving the bits\r
+// of latitude and longitude. There is a scale factor, so that grid represents\r
+// latitude and longitude value parts more than ~ 1/182.0444,\r
+// and precision represents the rest of the values.\r
+\r
+// So we pull each 2n-th bit out, and shift it n places back to the nth longitudinal bit\r
+// and we pull each 2n-th+1 bit out, and shift it n+1 places to the nth latitudinal bit,\r
+\r
+       unsigned long int lat_mask=1;\r
+       unsigned long int lon_mask=2;\r
+       unsigned long int lat_val = 0;\r
+       unsigned long int lon_val = 0;\r
+       struct point p;\r
+\r
+       int i;\r
+       for(i=0; i<16; i++) {\r
+               lat_val += (lat_mask & msp.grid) >> i;\r
+               lon_val += (lon_mask & msp.grid) >> (i+1);\r
+               lat_mask <<= 2;\r
+               lon_mask <<= 2;\r
+       }\r
+\r
+       //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val);\r
+\r
+       // Dont divide by magic1 until accounting for precision,\r
+       // because that would introduce rounding errors\r
+       p.lat = (double) lat_val ;//  magic1;\r
+       p.lon = (double) lon_val ;//  magic1;\r
+\r
+       //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon);\r
+\r
+       lat_mask=1;\r
+       lon_mask=2;\r
+       lat_val=0;\r
+       lon_val=0;\r
+\r
+       for (i=0; i<16; i++) {\r
+               lat_val += (lat_mask & msp.precision) >> i;\r
+               lon_val += (lon_mask & msp.precision) >> (i+1);\r
+               lat_mask <<= 2;\r
+               lon_mask <<= 2;\r
+       }\r
+\r
+       //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val);\r
+\r
+       p.lat += (double) lat_val / (magic2);\r
+       p.lon += (double) lon_val / (magic2);\r
+\r
+       p.lat *= 1/ (magic1);\r
+       p.lon *= 1/ (magic1);\r
+\r
+       //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon);\r
+\r
+       if (p.lon > 180) p.lon -= 360;\r
+       if (p.lat > 180) p.lat -= 360;\r
+       return p;\r
+}\r
+\r
+void explore_annot(struct annot_rec rec)\r
+{\r
+       char* header;\r
+       char* tail;\r
+       int taillength;\r
+\r
+       header = (char*)xmalloc(ANNOT_REC_HEAD_LEN);\r
+       memcpy(header, rec.buf, ANNOT_RECOS_TEXT);\r
+       memcpy(header+ANNOT_RECOS_TEXT+2*rec.text_length, rec.buf,\r
+               ANNOT_REC_HEAD_LEN-ANNOT_RECOS_TEXT);\r
+\r
+       tail = rec.buf+ANNOT_REC_HEAD_LEN+2*rec.text_length;\r
+       taillength = rec.length - ANNOT_REC_HEAD_LEN+2*rec.text_length;\r
+\r
+       printf("Record buffer\n", annot_type_name[rec.type]);\r
+       printbuf(rec.buf, rec.length);\r
+       printf("Record high buffer\n", annot_type_name[rec.type]);\r
+       printbufhigh(rec.buf, rec.length);\r
+       printf("Record wide header:\n", annot_type_name[rec.type]);\r
+       printbufwide(header, ANNOT_REC_HEAD_LEN);\r
+       printf("Record tail:\n");\r
+       printbuf(tail, taillength);\r
+       printf("Record wide tail:\n");\r
+       printbufwide(tail, taillength);\r
+       printf("Record tail as floats:\n");\r
+       printbufasfloat(tail, taillength);\r
+       printf("Record tail as points:\n");\r
+       printbufaspoints(tail, taillength);\r
+//     if (rec.type == ANNOT_TYPE_TEXT)\r
+//     {\r
+               //printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+//     }\r
+//     else if (rec.type == ANNOT_TYPE_OVAL )\r
+//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+//     else if (rec.type == ANNOT_TYPE_CIRCLE ))\r
+//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+       free(header);\r
+}\r
+\r
+void gpx_open_write_file_header(char* gpx_file_name)\r
+{\r
+       if (gpx_file_name)\r
+       {\r
+               gpx_file = fopen(gpx_file_name, "w");\r
+               if (gpx_file == NULL)\r
+               {\r
+                       fprintf(stderr, "Cannot open %s\n", optarg);\r
+                       exit(1);\r
+               }\r
+       }\r
+       else\r
+               return;\r
+\r
+       if (gpx_file!=NULL)\r
+       {\r
+               fprintf(gpx_file, GPX_HEADER1);\r
+               fprintf(gpx_file, GPX_HEADER2);\r
+               if (source_file_name)\r
+                       fprintf(gpx_file, "\t<desc>=\"This file was created from %s by %s\"</desc>\n",\r
+                                       source_file_name, GPX_THIS_PROGRAM);\r
+               // Some more tags we should add here\r
+               //      <name> Descriptive name of the GPX file\r
+               //      <desc> Description of the GPX file\r
+               //      <author> Name of the file's creator\r
+               //      <time> Creation date/time of the GPX file\r
+       }\r
+}\r
+\r
+void gpx_write_file_trailer()\r
+{\r
+       if (gpx_file!=NULL)\r
+       {\r
+               fprintf(gpx_file, GPX_FOOTER);\r
+           fclose(gpx_file);\r
+       }\r
+}\r
+\r
+void gpx_write_point(struct gpx_point pt, int pt_type, char* opt_elms)\r
+{\r
+       if (gpx_file!=NULL)\r
+       {\r
+               if (pt_type == GPX_TRKPT)\r
+                       fprintf(gpx_file, "\t\t");\r
+               else if (pt_type == GPX_RTEPT)\r
+                       fprintf(gpx_file, "\t");\r
+               fprintf(gpx_file, "\t<%s lat=\"%f\" lon=\"%f\">%s</%s>\n",\r
+                               gpxptypelabel[pt_type], pt.lat, pt.lon,\r
+                               opt_elms, gpxptypelabel[pt_type]);\r
+       }\r
+}\r
+\r
+void gpx_write_jour_point(struct jourwpt_rec * wpt)\r
+{\r
+       struct gpx_point pt;\r
+       char* opt_elms;\r
+       int optlen;\r
+\r
+       if (gpx_file==NULL)\r
+               return;\r
+\r
+       // For now we only deal with journey points which we matched to a pushpin.\r
+       // Later we need to allow for finding lat & lon in the journey stream itself\r
+       if (!wpt->pushpin)\r
+               return;\r
+       //printf("in gpx_write_jour_point\n");\r
+       //fflush(stdout);\r
+\r
+       optlen = strlen(wpt->pushpin->UdName) + strlen(wpt->pushpin->NoteShort) + 40;\r
+       opt_elms = (char*)xmalloc(optlen);\r
+\r
+       //printf("doing sprintf(opt_elms\n");\r
+       //fflush(stdout);\r
+\r
+       sprintf(opt_elms, "<name>%s</name><cmt>%s</cmt>",\r
+                       wpt->pushpin->UdName, wpt->pushpin->NoteShort);\r
+\r
+       pt.lat = wpt->pushpin->lat;\r
+       pt.lon = wpt->pushpin->lon;\r
+       pt.height = 0;\r
+\r
+       //printf("doing gpx_write_point\n");\r
+       //fflush(stdout);\r
+\r
+       gpx_write_point(pt, GPX_RTEPT, opt_elms);\r
+\r
+       free(opt_elms);\r
+\r
+       //printf("out of gpx_write_jour_point\n");\r
+       //fflush(stdout);\r
+\r
+}\r
+\r
+void gpx_write_jour_header()\r
+{\r
+       if(gpx_file!=NULL)\r
+       {\r
+               fprintf(gpx_file, "\t<rte>\n");\r
+               fprintf(gpx_file, "\t\t<name>Journey</name>\n");\r
+               fprintf(gpx_file, "\t\t<src>Extracted from main Journey</src>\n");\r
+       }\r
+}\r
+\r
+void gpx_write_jour_trailer()\r
+{\r
+       if(gpx_file!=NULL)\r
+               fprintf(gpx_file, "\t</rte>\n");\r
+\r
+}\r
+\r
+struct pushpin * ppin_by_UdId(int UdId)\r
+{\r
+       int i;\r
+\r
+       //printf("looking to match UdId %d to a pushpin\n", UdId);\r
+       //fflush(stdout);\r
+\r
+       if (UdId == 0)\r
+               return NULL;\r
+\r
+       for (i=0; i< MAX_PUSHPINS; i++)\r
+       {\r
+               //printf("Comparing to pushpin %d\n", i);\r
+               //fflush(stdout);\r
+               if(ppin_list[i] == NULL)\r
+                       return NULL;\r
+\r
+               //printf(" with UdId %ld ", (ppin_list[i])->UdId);\r
+               //fflush(stdout);\r
+               //printf(" and name %s\n", (ppin_list[i])->UdName);\r
+\r
+               if ((ppin_list[i]->UdId) == 0)\r
+                       return NULL;\r
+\r
+               if (ppin_list[i]->UdId == UdId)\r
+                       return ppin_list[i];\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+void gpx_write_pushpinlist ()\r
+{\r
+       int i;\r
+       struct gpx_point pt;\r
+       char* opt_elms;\r
+       int optlen;\r
+\r
+       if (gpx_file==NULL)\r
+               return;\r
+\r
+       for (i=0; i<MAX_PUSHPINS; i++)\r
+       {\r
+               if (ppin_list[i]==NULL)\r
+                       break;\r
+\r
+               optlen = strlen(ppin_list[i]->UdName) + strlen(ppin_list[i]->NoteShort) + 40;\r
+               opt_elms = (char*)xmalloc(optlen);\r
+\r
+               sprintf(opt_elms, "<name>%s</name><cmt>%s</cmt>",\r
+                               ppin_list[i]->UdName, ppin_list[i]->NoteShort);\r
+\r
+               pt.lat = ppin_list[i]->lat;\r
+               pt.lon = ppin_list[i]->lon;\r
+               pt.height = 0;\r
+\r
+               gpx_write_point(pt, GPX_WPT, opt_elms);\r
+       }\r
+       fprintf(gpx_file, "\n");\r
+}\r
+\r
+void gpx_write_annot_rec(struct annot_rec rec)\r
+{\r
+       int pt_type;\r
+       int p;\r
+       char opt_elms[200];\r
+       struct gpx_point pt;\r
+\r
+       if (! gpx_file)\r
+       {\r
+               return;\r
+       }\r
+\r
+       pt_type = GPX_TRKPT ;\r
+\r
+       // FIXME why do I need to assign memory for this?\r
+\r
+       if (use_gpx_route)\r
+               pt_type = GPX_RTEPT;\r
+       switch (rec.type)\r
+       {\r
+               case ANNOT_TYPE_LINE:\r
+\r
+               // FIXME lots of format and name info to be added here\r
+               if(use_gpx_route)\r
+               {\r
+                       fprintf(gpx_file, "\t<rte>\n");\r
+                       fprintf(gpx_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
+                                       rec.annot_num, annot_type_name[rec.type]);\r
+                       fprintf(gpx_file, "\t\t<name>RT%04d</name>\n", rec.annot_num);\r
+               }\r
+               else\r
+               {\r
+                       fprintf(gpx_file, "\t<trk>\n");\r
+                       fprintf(gpx_file, "\t\t<name>TK%04d</name>\n", rec.annot_num);\r
+                       fprintf(gpx_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
+                                       rec.annot_num, annot_type_name[rec.type]);\r
+                       fprintf(gpx_file, "\t\t<trkseg>\n");\r
+               }\r
+\r
+               for (p=0; p < rec.line_points; p++)\r
+               {\r
+                       pt=gpx_get_point(rec.buf+annot_head_len[rec.type]+12*p);\r
+                       if(use_gpx_route)\r
+                               sprintf(opt_elms, "<name>rp%04d</name>", p);\r
+                       else\r
+                               // we need to include a name for trackpoints\r
+                               // for them to be recognised by easygps.\r
+                               sprintf(opt_elms, "<name>tp%04d</name>", p);\r
+                       gpx_write_point(pt, pt_type, opt_elms);\r
+               }\r
+               if(use_gpx_route)\r
+                       fprintf(gpx_file, "\t</rte>\n");\r
+               else\r
+                       fprintf(gpx_file, "\t\t</trkseg>\n\t</trk>\n");\r
+\r
+               case ANNOT_TYPE_OVAL:\r
+               case ANNOT_TYPE_TEXT:\r
+               case ANNOT_TYPE_CIRCLE:\r
+               default:\r
+                       break;\r
+       }\r
+}\r
+\r
+int readbytes(FILE* file, char* buf, int bytes2read)\r
+{\r
+       // cant I just do this with fread?\r
+       int i;\r
+//     int status;\r
+/*     int readbyte;\r
+       for (i=0; i<bytes2read; i++)\r
+       {\r
+               readbyte = getc(file);\r
+               if(readbyte==EOF)\r
+               {\r
+               fprintf(stderr, "Unexpected end of file while reading %i bytes\n",bytes2read);\r
+               printf("Read %d of a required %d bytes\n", i+1, bytes2read);\r
+               printf("Dumping the buffer read before unexpected EOF\n");\r
+               printbuf(buf,i);\r
+               fflush(stdout);\r
+               return(1);\r
+               //exit(1);\r
+               }\r
+               buf[i] = readbyte;\r
+               if (verbose_flag > 5)\r
+               {\r
+                       //printf("read byte from file %#x=%u=%c\n", readbyte,readbyte,readbyte);\r
+                       //fflush(stdout);\r
+\r
+               }\r
+       }\r
+*/\r
+       i = fread(buf, 1, bytes2read, file);\r
+       if (i<bytes2read)\r
+       {\r
+               if (feof(file))\r
+                       printf("Unexpected end of file\n");\r
+               else if (ferror(file))\r
+                       perror("Unexpected error while reading from file");\r
+        printf("Read %d of a required %d bytes\n", i+1, bytes2read);\r
+        printf("Dumping the buffer read before unexpected EOF or error\n");\r
+        printbuf(buf,i);\r
+        fflush(stdout);\r
+        return(i);\r
+       }\r
+\r
+       if (verbose_flag > 5)\r
+       {\r
+               printf("Readbytes: Read %d bytes from file\n",bytes2read);\r
+               printbuf(buf, bytes2read);\r
+               fflush(stdout);\r
+               if (gpx_file)\r
+                       fflush(gpx_file);\r
+\r
+       }\r
+       return(i);\r
+}\r
+\r
+struct annot_rec read_annot_rec(int annot_num)\r
+{\r
+       // new improved version!\r
+\r
+       int status;\r
+       int i;\r
+       struct annot_rec rec;\r
+       rec.buf = (char*)xmalloc(ANNOT_REC_HEAD_LEN);\r
+       // This read can fail because I have miscalculated number of records\r
+       // So exit gracefully\r
+       status = readbytes(annot_file, rec.buf, ANNOT_REC_HEAD_LEN);\r
+       if (status!=ANNOT_REC_HEAD_LEN)\r
+       {\r
+               gpx_write_file_trailer();\r
+               // exit(1)\r
+               // should do some cleaning up here\r
+               return rec;\r
+       }\r
+\r
+       rec.type = *(int*)(rec.buf+ANNOT_RECOS_TYPE);\r
+       rec.annot_num = *(int*)(rec.buf+ANNOT_RECOS_ANUM);\r
+       rec.text_length = *(int*)(rec.buf+ANNOT_RECOS_TEXTLEN);\r
+       rec.line_points=0;\r
+       if (rec.type == ANNOT_TYPE_LINE)\r
+               rec.line_points = *(int*)(rec.buf+ANNOT_RECOS_LINENUMPOINTS);\r
+       rec.length = annot_rec_len[rec.type] + 2*rec.text_length + 12*rec.line_points;\r
+\r
+       printf("Got annotation %d with internal id %d, of type %s, text length %d, and %d line points\n",\r
+                       annot_num+1, rec.annot_num, annot_type_name[rec.type],\r
+                       rec.text_length, rec.line_points);\r
+\r
+       rec.buf = (char*)xrealloc(rec.buf, rec.length);\r
+       status = readbytes(annot_file, rec.buf+ANNOT_REC_HEAD_LEN, rec.length - ANNOT_REC_HEAD_LEN);\r
+       if (status!=(rec.length - ANNOT_REC_HEAD_LEN))\r
+       {\r
+               gpx_write_file_trailer();\r
+               exit(1);\r
+       }\r
+\r
+       if(rec.text_length>0)\r
+       {\r
+               rec.text=(char*)xmalloc(rec.text_length+1);\r
+               rec.text[rec.text_length]=0x0;\r
+               for (i=0;i<rec.text_length;i++)\r
+                       rec.text[i]=rec.buf[ANNOT_RECOS_TEXT+ 2*i];\r
+               //if (verbose_flag > 1)\r
+\r
+               printf("The sb text in the box is: %s\n", rec.text);\r
+       }\r
+\r
+       if (verbose_flag > 4)\r
+       {\r
+               printf("Recognised record with length %i\n",rec.length);\r
+               printbuf(rec.buf, rec.length);\r
+       }\r
+\r
+       return rec;\r
+}\r
+\r
+void process_annotations_stream(char* annot_file_name)\r
+{\r
+       // Read the annotation file header\r
+\r
+       int i;\r
+       int num_annotations;\r
+//     int file_pos = ANNOT_FILE_HEAD_LEN;\r
+       annot_file_header file_header = (annot_file_header)xmalloc(ANNOT_FILE_HEAD_LEN);\r
+       int status;\r
+       struct annot_rec rec;\r
+       char* checkEOF;\r
+\r
+       if ((annot_file = fopen(annot_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Quitting because I cannot open %s\n", annot_file_name);\r
+               exit(1);\r
+       }\r
+\r
+       status=readbytes(annot_file, file_header, ANNOT_FILE_HEAD_LEN);\r
+       if (status!=ANNOT_FILE_HEAD_LEN)\r
+       {\r
+               printf("Cant make any more sense of annotations stream, continuing\n");\r
+               return;\r
+       }\r
+\r
+    // file_pos is for debugging only\r
+\r
+       for (i=1; i<8; i++)\r
+               if ( file_header[i] != std_annotfile_header[i] )\r
+                       printf("Nonstandard annotations file header, header[%i]=0x%x, normal value is 0x%x\n",\r
+                                       i, file_header[i], std_annotfile_header[i] );\r
+\r
+       num_annotations = *(int*)(file_header+8);\r
+\r
+               if (verbose_flag > 1)\r
+               {\r
+                       printf("Annotations file header indicates %i annotations in file\n",\r
+                                       num_annotations);\r
+               }\r
+\r
+       if (verbose_flag > 4)\r
+       {\r
+               printf("Dumping file header:\n");\r
+               printbuf(file_header, ANNOT_FILE_HEAD_LEN);\r
+       }\r
+\r
+       /*\r
+       ** Read all the annotation records\r
+       */\r
+       for (i=0; i < num_annotations; i++)\r
+       {\r
+           rec = read_annot_rec(i);\r
+\r
+               if (explore_flag)\r
+                       explore_annot(rec);\r
+\r
+               gpx_write_annot_rec(rec);\r
+\r
+               free(rec.buf);\r
+               if (rec.text_length>0)\r
+                       free(rec.text);\r
+       }\r
+\r
+       // Check that we are at the end of annotation file\r
+\r
+       checkEOF = xmalloc(4);\r
+       status=readbytes(annot_file, checkEOF, 4);\r
+       if ( (status!=4) || (checkEOF[0]!=0) || (checkEOF[1]!=0)\r
+                       || (checkEOF[2]!=0) || (checkEOF[3]!=0) || (getc(annot_file)!=EOF) )\r
+       {\r
+               fprintf (stderr, "Did not finish reading annotation file at EOF\n");\r
+               if (gpx_file)\r
+                       fprintf(gpx_file, GPX_FOOTER);\r
+       }\r
+       free(checkEOF);\r
+       fclose(annot_file);\r
+       fflush(stdout);\r
+       fflush(gpx_file);\r
+}\r
+\r
+struct jourwpt_rec * read_journey_rec(int jour_num)\r
+{\r
+       int i;\r
+       int status;\r
+       int readlen1 = JOURWPT_REC_HEAD_LEN;\r
+       int readlen2;\r
+       int readlen3;\r
+       char c;\r
+       struct jourwpt_rec * rec = (struct jourwpt_rec *)xmalloc(sizeof(struct jourwpt_rec));\r
+\r
+       rec->buf = (char*)xmalloc(readlen1);\r
+\r
+       status = readbytes(jour_file, rec->buf, readlen1);\r
+       if (status!=readlen1)\r
+       {\r
+               printf("Unexpected EOF while reading Journey route point %d part 1.\n", jour_num);\r
+               printf("Dumping Journey route point buffer read so far\n");\r
+               printbuf(rec->buf, status);\r
+               //FIXME free rec\r
+               return NULL;\r
+       }\r
+\r
+       // FIXME careful here\r
+       c = rec->buf[0];\r
+       rec->UdId = c;\r
+\r
+       c = rec->buf[JOURWPT_RECOS_STR1LEN];\r
+\r
+       rec->text1_length = (int)c;\r
+\r
+       if (verbose_flag > 5)\r
+       {\r
+               printf("Reading Journey routepoint, got buf part1, text1 len = %d\n",\r
+                               rec->text1_length);\r
+               printbuf(rec->buf, readlen1);\r
+       }\r
+\r
+       readlen2 = rec->text1_length+4;\r
+\r
+       rec->buf = (char*)xrealloc(rec->buf, readlen1 + readlen2);\r
+       status = readbytes(jour_file, rec->buf+readlen1, readlen2);\r
+       if (status!=readlen2)\r
+       {\r
+               printf("Unexpected EOF while reading Journey route point %d part 2.\n", jour_num);\r
+               printf("Dumping Journey route point buffer read so far\n");\r
+               printbuf(rec->buf, readlen1+status);\r
+               //FIXME free rec\r
+               return NULL;\r
+       }\r
+\r
+       c = rec->buf[JOURWPT_RECOS_STR2LEN + rec->text1_length];\r
+       rec->text2_length = (int)c;\r
+       rec->buf_length = JOUR_WPTREC_LEN + rec->text1_length + 2*rec->text2_length;\r
+\r
+       if (verbose_flag > 5)\r
+       {\r
+               printf("got buf part2, text2 len = %d\n", rec->text2_length);\r
+               printbuf(rec->buf, readlen1 + readlen2);\r
+       }\r
+       readlen3 = rec->buf_length  - readlen1 - readlen2;\r
+\r
+       rec->buf = (char*)xrealloc(rec->buf, rec->buf_length);\r
+       status = readbytes(jour_file, rec->buf+readlen1+readlen2, readlen3);\r
+       if (status!=readlen3)\r
+       {\r
+               printf("Unexpected EOF while reading Journey route point %d part 3.\n", jour_num);\r
+               printf("Dumping Journey route point buffer read so far\n");\r
+               printbuf(rec->buf, readlen1+readlen2+status);\r
+               //FIXME free rec\r
+               return NULL;\r
+       }\r
+\r
+       rec->text1=(char*)xmalloc(rec->text1_length+1);\r
+       rec->text2=(char*)xmalloc(rec->text2_length+1);\r
+       rec->text1[rec->text1_length]=0;\r
+       rec->text2[rec->text2_length]=0;\r
+       memcpy(rec->text1, rec->buf+JOURWPT_RECOS_STR1, rec->text1_length);\r
+       for (i=0; i<rec->text2_length; i++)\r
+               rec->text2[i]=rec->buf[JOURWPT_RECOS_STR2 + rec->text1_length+2*i];\r
+\r
+       if (verbose_flag > 3)\r
+               printf("got Journey routepoint UdId %d, text1 '%s', text2 '%s', length %d\n",\r
+                       rec->UdId, rec->text1, rec->text2, rec->buf_length);\r
+\r
+       rec->pushpin = ppin_by_UdId(rec->UdId);\r
+\r
+       if (rec->pushpin != NULL)\r
+       {\r
+               if (verbose_flag > 5)\r
+               {\r
+                       printf("Found probable pushpin match\n");\r
+                       printf("pushpin name is: %s\n", rec->pushpin->UdName);\r
+                       printf("Pushpin short note is: %s\n", rec->pushpin->NoteShort);\r
+                       //printf("Pushpin long note is: %s\n", rec->pushpin->NoteLong);\r
+               }\r
+\r
+               gpx_write_jour_point(rec);\r
+       }\r
+       else\r
+       {\r
+               printf("*** Warning *** Ignoring route point '%s' without matching pushpin\n",\r
+                               rec->text1);\r
+               printf("(yes, I should do someting more clever than this).\n");\r
+               if (rec->UdId)\r
+                       printf("There should have been a matching pushin because UdId=%d\n", rec->UdId);\r
+       }\r
+       fflush(stdout);\r
+\r
+       if (verbose_flag > 4)\r
+       {\r
+               printf("Dumping the recognised Journey waypoint record\n");\r
+               printbuf(rec->buf, rec->buf_length);\r
+       }\r
+       return rec;\r
+}\r
+\r
+void process_journey_stream (char* jour_file_name)\r
+{\r
+       int journey_num_pts;\r
+       int j;\r
+       int readbyte;\r
+       static int verify_eof_flag = 0;\r
+       char* jour_file_header = (char*)xmalloc(JOUR_FILE_HEAD_LEN);\r
+       char* jour_file_trailer;\r
+       int max_read_more = 10000;\r
+       int readmore=0;\r
+       int status;\r
+       char readmorebuf[10000];\r
+       struct jourwpt_rec * rec;\r
+\r
+       gpx_write_jour_header();\r
+\r
+       printf("Processing Journey stream\n");\r
+       fflush(stdout);\r
+       fflush(gpx_file);\r
+\r
+\r
+       if ((jour_file = fopen(jour_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Quitting because I cannot open %s\n", jour_file_name);\r
+               exit(1);\r
+       }\r
+\r
+       status = readbytes(jour_file, jour_file_header, JOUR_FILE_HEAD_LEN);\r
+       if (status!=JOUR_FILE_HEAD_LEN)\r
+       {\r
+               printf("Unexpected EOF in the Journey stream\n");\r
+               gpx_write_jour_trailer();\r
+               return;\r
+       }\r
+\r
+       journey_num_pts = *(int*)(jour_file_header+JOUR_FILEOS_NUMREC);\r
+       printf("got Journey file header with %d waypoints\n", journey_num_pts);\r
+       if (verbose_flag > 4)\r
+       {\r
+               printbuf(jour_file_header, JOUR_FILE_HEAD_LEN);\r
+       }\r
+\r
+       for (j=0; j< journey_num_pts; j++)\r
+       {\r
+               rec = read_journey_rec(j);\r
+               if (rec==NULL)\r
+               {\r
+                       printf("Closing stream and skipping rest of Journey stream processing because I read a bad record\n");\r
+                       fclose(jour_file);\r
+                       printf("Writing gpx route for Journey\n");\r
+                       fflush(stdout);\r
+\r
+                       gpx_write_jour_trailer();\r
+\r
+                       printf("Finnished closing Journey stream after error.\n");\r
+                       return;\r
+               }\r
+       }\r
+\r
+       jour_file_trailer = (char*)xmalloc(JOUR_FILE_TAIL_LEN);\r
+\r
+       status = readbytes(jour_file, jour_file_trailer, JOUR_FILE_TAIL_LEN);\r
+       if (status!=JOUR_FILE_TAIL_LEN)\r
+       {\r
+               printf("Unexpected EOF while reading journey stream trailer\n");\r
+       }\r
+\r
+       if (verbose_flag > 4)\r
+       {\r
+               printf("got Journey file trailer\n");\r
+               printbuf(jour_file_trailer, JOUR_FILE_TAIL_LEN);\r
+       }\r
+\r
+       if ((readbyte = getc(jour_file))!=EOF)\r
+       {\r
+               fprintf (stderr, "Did not finish reading journey file at EOF\n");\r
+\r
+               do {\r
+                       readmorebuf[readmore]=(char)readbyte;\r
+                       readmore++;\r
+                       if (readmore>max_read_more)\r
+                               break;\r
+               } while ((readbyte = getc(jour_file))!=EOF);\r
+\r
+               printf("read a further %d bytes past expected eof\n",readmore);\r
+               printbuf(readmorebuf, readmore);\r
+       }\r
+\r
+    fclose(jour_file);\r
+       printf("Writing gpx route for Journey\n");\r
+       fflush(stdout);\r
+\r
+       gpx_write_jour_trailer();\r
+\r
+       printf("Finnished proccessing Journey stream.\n");\r
+       fflush(stdout);\r
+       fflush(gpx_file);\r
+}\r
+\r
+void read_ppin_list_csv(char* ppin_file_name)\r
+// for reading my old style csv temp file for ppins\r
+{\r
+       int pinnum;\r
+       int params_read;\r
+       char ppin_line[500+MAX_PPIN_MEMO];\r
+       char ppin_line_strings[500+MAX_PPIN_MEMO];\r
+       struct pushpin * ppin;\r
+       char* status;\r
+       int UdNameLen=0;\r
+       int NoteShortLen=0;\r
+       int NoteLongLen=0;\r
+\r
+       printf("Annalysing the pushpin temp file\n");\r
+\r
+       for (pinnum=0; pinnum < MAX_PUSHPINS; pinnum++)\r
+               ppin_list[pinnum] = NULL;\r
+\r
+       if ((ppin_file = fopen(ppin_file_name, "r")) == NULL)\r
+       {\r
+               fprintf(stderr, "Cannot open %s\n", ppin_file_name);\r
+               exit(1);\r
+       }\r
+\r
+       pinnum=0;\r
+       while (!feof( ppin_file))\r
+       {\r
+               //printf("Reading pushpin %d\n", pinnum);\r
+               //fflush(stdout);\r
+\r
+               ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin));\r
+\r
+               status=fgets(ppin_line, 500+MAX_PPIN_MEMO, ppin_file);\r
+\r
+               if (status==NULL)\r
+               {\r
+                       printf("oops, trying to read empty line\n", pinnum);\r
+                       break;\r
+\r
+               }\r
+               else\r
+               {\r
+                       //printf("Read ppin temp line: %s\n", ppin_line);\r
+                       //fflush(stdout);\r
+\r
+                       params_read = sscanf(ppin_line, "%ld, %ld, %ld, %d, %d, %d, %[^\n]",\r
+                               &(ppin->UdId), &(ppin->Grid), &(ppin->Precision),\r
+                               &UdNameLen, &NoteShortLen, &NoteLongLen, ppin_line_strings);\r
+\r
+                       printf("Got pushpin UdId %ld Grid %d Precision %d ppin_line_strings %s\n",\r
+                                       ppin->UdId, ppin->Grid, ppin->Precision, ppin_line_strings);\r
+                       fflush(stdout);\r
+\r
+                       if (params_read == 7)\r
+                       {\r
+                               ppin->UdName = (char*)xmalloc(UdNameLen+1);\r
+                               memcpy(ppin->UdName, ppin_line_strings, UdNameLen);\r
+                               ppin->UdName[UdNameLen]=0;\r
+\r
+                               ppin->NoteShort = (char*)xmalloc(NoteShortLen+1);\r
+                               memcpy(ppin->NoteShort, ppin_line_strings+UdNameLen, NoteShortLen);\r
+                               ppin->NoteShort[NoteShortLen]=0;\r
+\r
+//                             ppin->NoteLong = (char*)xmalloc(NoteLongLen+1);\r
+//                             memcpy(ppin->NoteLong, ppin_line_strings+UdNameLen+NoteShortLen, NoteLongLen);\r
+//                             ppin->NoteLong[NoteLongLen]=0;\r
+\r
+                               //printf("Read %d parameters ok\n", params_read);\r
+                               //fflush(stdout);\r
+\r
+\r
+                               ppin_list[pinnum]=ppin;\r
+                       //      printf("saving pushpin_linst[%d]: UdId %ld lat %g lon %g UdName %s\n",\r
+                       //              pinnum, ppin->UdId, ppin->lat, ppin->lon, ppin->UdName);\r
+                       //      fflush(stdout);\r
+                               pinnum++;\r
+                       }\r
+                       else\r
+                       {\r
+                               printf("freeing this ppin (was# %d) because it did not read properly\n",\r
+                                               pinnum);\r
+                               free(ppin);\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       fclose(ppin_file);\r
+       printf("Read %d pushpins, now writing to gpx\n", pinnum);\r
+\r
+}\r
+\r
+int check_file_empty(char* filename)\r
+{\r
+       int readchar;\r
+       FILE* file=fopen(filename, "rb");\r
+       // also check if the file exists\r
+       if (file==NULL)\r
+               return 1;\r
+       readchar = fgetc(file);\r
+       if (readchar == EOF)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+void process_pushpin_file(char* ppin_file_name)\r
+{\r
+       int i=0;\r
+       struct point p;\r
+       struct ms_point msp;\r
+\r
+       // dont try and open a empty mdb file\r
+       if (check_file_empty(ppin_file_name))\r
+               return;\r
+\r
+       read_ppin_list(ppin_file_name);\r
+       //read_ppin_list_csv(ppin_file_name);\r
+\r
+       // set lat & lon for all pushpins\r
+       while(ppin_list[i] && (i<MAX_PUSHPINS))\r
+       {\r
+               msp.grid = ppin_list[i]->Grid;\r
+               msp.precision = ppin_list[i]->Precision;\r
+               p = ms2latlong(msp);\r
+\r
+               ppin_list[i]->lat = p.lat;\r
+               ppin_list[i]->lon = p.lon;\r
+\r
+       if (verbose_flag > 3)\r
+                       printf("Decoded pushpin %d lat %f, lon %f, UdName %s, NoteShort %s\n",\r
+                               ppin_list[i]->UdId, ppin_list[i]->lat, ppin_list[i]->lon,\r
+                               ppin_list[i]->UdName, ppin_list[i]->NoteShort);\r
+\r
+               i++;\r
+       }\r
+\r
+       gpx_write_pushpinlist();\r
+\r
+       printf("Finished reading pushpins\n");\r
+       fflush(stdout);\r
+       fflush(gpx_file);\r
+}\r
+\r
+void show_usage()\r
+{\r
+       printf("st2gpx - Export data from MS Streets & Trips and Autoroute to GPX format\n\n");\r
+       printf("Usage: st2gpx [-hre] [-v verbose-level] [-a annotations-file] [-u userdata-file] ");\r
+       printf("[-j journey-file] [-G gpx-file] stfile\n\n");\r
+       printf("-h : Help (this text)\n");\r
+       printf("-r : Export drawn-lines as routes instead of tracks\n");\r
+       printf("-e : Explore data furhter\n");\r
+       printf("-v [n]              : Set debugging verbosity to 'n' (0-6, default 2)\n");\r
+       printf("-u userdata-file    : Process pushpins in (mdb) file userdata-file\n");\r
+       printf("-j journey-file     : Process Journey in file journey-file\n");\r
+       printf("-a annotations-file : Process Annotations in file annotations-file\n");\r
+       printf("-G gpx-file         : Write output to gpx-file\n");\r
+       exit(0);\r
+}\r
+\r
+void xsystem(char* syscmd)\r
+// this is not ANSI\r
+{\r
+       int status;\r
+       printf("%s \n", syscmd);\r
+       _flushall();\r
+       status = system(syscmd);\r
+       if (status)\r
+               fprintf(stderr, "system call returned an error\n");\r
+}\r
+\r
+main(int argc, char** argv)\r
+{\r
+       int c;\r
+       static int verify_eof_flag = 0;\r
+       char* jour_file_name=NULL;\r
+       char* annot_file_name=NULL;\r
+       char* ppin_file_name=NULL;\r
+       char* gpx_file_name=NULL;\r
+\r
+       char syscmd[1000];\r
+    char cmddrv[_MAX_DRIVE];\r
+    char cmddir[_MAX_DIR];\r
+    char cmdfilename[_MAX_PATH];\r
+    char cmdext[_MAX_EXT];\r
+       char cmdpath[_MAX_PATH];\r
+\r
+       int debug_wait_flag=0;\r
+\r
+       while (1)\r
+    {\r
+               static struct option long_options[] =\r
+        {\r
+                       {"file",    required_argument, 0, 'f'},\r
+                       {"outfile",    required_argument, 0, 'F'},\r
+                       {"verbose", optional_argument, 0, 'v'},\r
+                       {"explore", no_argument,       &explore_flag, 1},\r
+                       {"route",    no_argument, &use_gpx_route, 1},\r
+                       {0, 0, 0, 0} // what is this for?\r
+        };\r
+               /* getopt_long stores the option index here. */\r
+               int option_index = 0;\r
+\r
+               //    c = getopt_long (argc, argv, "v::bqderf:F:",\r
+               //                     long_options, &option_index);\r
+               c = getopt(argc, argv, "hu:j:a:G:rv::ew");\r
+\r
+               /* Detect the end of the options. */\r
+               if (c == -1)\r
+                       break;\r
+\r
+               switch (c)\r
+        {\r
+        case 0:\r
+                       /* If this option set a flag, do nothing else now. */\r
+                       break;\r
+\r
+        case 'h':\r
+                       show_usage();\r
+                       break;\r
+\r
+        case 'u':\r
+                       // read a UserData (pushpin) file directly\r
+                       free(ppin_file_name);\r
+                       ppin_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(ppin_file_name, optarg);\r
+                       if (verbose_flag > 1)\r
+                               printf("Analysing UserData (pushpin) stream in file %s\n\n", jour_file_name);\r
+           break;\r
+\r
+       case 'j':\r
+                       // read a Journey file directly\r
+                       free(jour_file_name);\r
+                       jour_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(jour_file_name, optarg);\r
+                       if (verbose_flag > 1)\r
+                               printf("Analysing Journey stream in file %s\n\n", jour_file_name);\r
+            break;\r
+\r
+        case 'a':\r
+                       // read an annotation file directly\r
+                       annot_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(annot_file_name, optarg);\r
+                       if (verbose_flag > 1)\r
+                               printf("Analysing Annotation stream in file %s\n\n", annot_file_name);\r
+            break;\r
+\r
+        case 'G':\r
+                       gpx_file_name = (char*)xmalloc(200);\r
+                       strcpy(gpx_file_name, optarg);\r
+                       if (verbose_flag > 1)\r
+                               printf("Writing GPX output to file %s\n\n", gpx_file_name);\r
+            break;\r
+\r
+        case 'r':\r
+                       use_gpx_route=1;\r
+            break;\r
+\r
+               case 'v':\r
+                       if (optarg==NULL)\r
+                               verbose_flag=5;\r
+                       else\r
+                               verbose_flag = atoi(optarg);\r
+                       break;\r
+\r
+        case 'e':\r
+                       explore_flag = 1;\r
+                       break;\r
+\r
+        case 'w':\r
+                       debug_wait_flag = 1;\r
+                       break;\r
+\r
+        case '?':\r
+                       /* getopt_long already printed an error message. */\r
+                       show_usage();\r
+                       break;\r
+\r
+        default:\r
+                       show_usage();\r
+                       abort ();\r
+        }\r
+    }\r
+\r
+       if (optind == argc-1)\r
+       {\r
+                       source_file_name = (char*)xmalloc(strlen(argv[optind])+1);\r
+                       strcpy(source_file_name, argv[optind]);\r
+                       if (verbose_flag > 1)\r
+                               printf("Analysing autoroute file %s\n\n", source_file_name);\r
+                       if (ppin_file_name==NULL)\r
+                       {\r
+                               ppin_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
+                               sprintf(ppin_file_name, "%s.Contents\\UserData.mdb", source_file_name);\r
+                       }\r
+                       if (jour_file_name==NULL)\r
+                       {\r
+                               jour_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
+                               sprintf(jour_file_name, "%s.Contents\\Journey", source_file_name);\r
+                       }\r
+                       if (annot_file_name==NULL)\r
+                       {\r
+                               annot_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
+                               sprintf(annot_file_name, "%s.Contents\\Annotations", source_file_name);\r
+                       }\r
+                       if (gpx_file_name==NULL)\r
+                       {\r
+                               gpx_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
+                               // should remove the est or axe suffix\r
+                               sprintf(gpx_file_name, "%s.gpx", source_file_name);\r
+                       }\r
+       }\r
+       else if (optind < argc-1)\r
+       {\r
+           printf("Unrecognised option %s\n", argv[optind+1]);\r
+               show_usage();\r
+    }\r
+       else\r
+       {\r
+               if (verbose_flag > 1)\r
+                       printf("Not analysing any core S&T or autoroute file\n");\r
+       }\r
+\r
+       if (source_file_name)\r
+       {\r
+               // Open the compound file using the istorage utility\r
+               // I probably should do this in a library and use streams instead of files\r
+\r
+               // Find the path for istorage from the path in argv[0]\r
+\r
+               // this is not ANSI\r
+               _splitpath(argv[0], cmddrv, cmddir, cmdfilename, cmdext);\r
+               sprintf(cmdpath, "%s%s", cmddrv, cmddir);\r
+\r
+               sprintf(syscmd, "%sistorage\\istorage.exe %s", cmdpath, source_file_name);\r
+               xsystem(syscmd);\r
+\r
+               // clean up previous copy of this. It should already have been deleted...\r
+               sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name);\r
+               xsystem(syscmd);\r
+\r
+               sprintf(syscmd, "rename %s.Contents\\UserData. UserData.mdb", source_file_name);\r
+               xsystem(syscmd);\r
+       }\r
+\r
+       // begin processing the files\r
+       gpx_open_write_file_header(gpx_file_name);\r
+\r
+       if (ppin_file_name)\r
+               process_pushpin_file(ppin_file_name);\r
+       if (jour_file_name)\r
+               process_journey_stream(jour_file_name);\r
+       if (annot_file_name)\r
+               process_annotations_stream(annot_file_name);\r
+\r
+       gpx_write_file_trailer();\r
+\r
+\r
+       // Clean up the compound file directory\r
+       if (source_file_name)\r
+       {\r
+               sprintf(syscmd, "echo y|del %s.Contents", source_file_name);\r
+               xsystem(syscmd);\r
+\r
+       // just for debuging\r
+       if (debug_wait_flag)\r
+       {\r
+               fprintf(stderr, "kill that ado connection!\n");\r
+               fprintf(stderr, "Hit any key to continue\n");\r
+               getchar();\r
+       }\r
+\r
+               // how do I do this?\r
+               sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name);\r
+               xsystem(syscmd);\r
+\r
+               sprintf(syscmd, "rmdir %s.Contents", source_file_name);\r
+               xsystem(syscmd);\r
+       }\r
+\r
+       // just for debuging\r
+       if (debug_wait_flag)\r
+       {\r
+               fprintf(stderr, "Hit any key to continue\n");\r
+               getchar();\r
+       }\r
+}\r
diff --git a/st2gpx/src/st2gpx.dsp b/st2gpx/src/st2gpx.dsp
new file mode 100644 (file)
index 0000000..1458989
--- /dev/null
@@ -0,0 +1,134 @@
+# Microsoft Developer Studio Project File - Name="st2gpx" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=st2gpx - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "st2gpx.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "st2gpx.mak" CFG="st2gpx - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "st2gpx - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "st2gpx - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "st2gpx - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "st2gpx - Win32 Release"\r
+# Name "st2gpx - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\getopt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pushpins.cpp\r
+\r
+!IF  "$(CFG)" == "st2gpx - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
+\r
+# ADD CPP /W4\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\st2gpx.c\r
+\r
+!IF  "$(CFG)" == "st2gpx - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
+\r
+# ADD CPP /Za\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\getopt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pushpins.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/st2gpx/src/st2gpx.dsw b/st2gpx/src/st2gpx.dsw
new file mode 100644 (file)
index 0000000..19486fe
--- /dev/null
@@ -0,0 +1,41 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "VCADO"="..\..\..\sw\5191\Rosetta\CPP\#Import-upg\Vcado.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "st2gpx"=.\st2gpx.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r